怎样控制Qt标题栏(How can I handle events in the titlebar and change its color etc ? )

因个人需要,要修改Qt Widget的标题栏,网上找了大半天,没有得到答案,但发现问的人比较多

 所以现将找到的此文分享一下.

(原文:http://www.qtsoftware.com/developer/faqs/faq.2007-04-25.2011048382)

 

 

 

How can I handle events in the titlebar and change its color etc ?

Answer:

 

 

The titlebar belongs to the OS and we don't have control over that one. You can create your own titlebar, but note that this requires some work. In order to create your own titlebar then make a QWidget subclass that contains three toolbuttons that handle the close, minimize and maximize events in addition to the moving of the window. Then make a QFrame subclass which does not have a titlebar provided via the window system. This is done by setting the Qt::FramelessWindowHint window flag, however this will make it impossible to resize or move the window via the window system. What can be done is you can add your custom titlbar as a private member to the frame and add the it first to the frame's vertical layout. The frame also needs a content widget which allows widgets to be added to it. Finally the QFrame subclass needs to reimplement the mouse events to handle the resizing and moving of the window. The example below demonstrates how this can be achieved.
(大概意思,也不知正不正确)
  标题栏属于操作系统(控制),并且我们确实也没有控制它.你可以创建你自己的标题栏,但是这要花你很多精力.
为了创建你自己的包含最大化,最小化,关闭按钮,以及可以移动窗口的标题栏,你必须从QWidget派生一个子类.同时从
QFrame派生一个子类,为使些子类不要从窗口系统得到标题栏,设置 Qt::FramelessWindowHint 窗口标记,
然而这又使得窗口不能通过窗口系统移动和缩放.
你可以将你自己的标题栏做为一个私有成员加到你的QFrame子类中,然后先将它添加到你的QFrame子类的垂直布局器中,
再在你的QFrame子类中添加一个content widget,以做为其它部件的容器(注:相当于窗口客户区).最后你的QFrame子类需要重载一些鼠标事件以控制窗口的缩放与移动.
下面的例子说明了它是怎样实现的.
#include <QApplication>
#include <QtGui>
#include <QLayout>
#include <QStyle>

class TitleBar : public QWidget
{
Q_OBJECT
public:
TitleBar(QWidget *parent)
{
// Don't let this widget inherit the parent's backround color
setAutoFillBackground(true);
// Use a brush with a Highlight color role to render the background
setBackgroundRole(QPalette::Highlight);

minimize = new QToolButton(this);
maximize = new QToolButton(this);
close= new QToolButton(this);

// Use the style to set the button pixmaps
QPixmap pix = style()->standardPixmap(QStyle::SP_TitleBarCloseButton);
close->setIcon(pix);

maxPix = style()->standardPixmap(QStyle::SP_TitleBarMaxButton);
maximize->setIcon(maxPix);

pix = style()->standardPixmap(QStyle::SP_TitleBarMinButton);
minimize->setIcon(pix);

restorePix = style()->standardPixmap(QStyle::SP_TitleBarNormalButton);

minimize->setMinimumHeight(20);
close->setMinimumHeight(20);
maximize->setMinimumHeight(20);


QLabel *label = new QLabel(this);
label->setText("Window Title");
parent->setWindowTitle("Window Title");

QHBoxLayout *hbox = new QHBoxLayout(this);

hbox->addWidget(label);
hbox->addWidget(minimize);
hbox->addWidget(maximize);
hbox->addWidget(close);

hbox->insertStretch(1, 500);
hbox->setSpacing(0);
setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);

maxNormal = false;

connect(close, SIGNAL( clicked() ), parent, SLOT(close() ) );
connect(minimize, SIGNAL( clicked() ), this, SLOT(showSmall() ) );
connect(maximize, SIGNAL( clicked() ), this, SLOT(showMaxRestore() ) );
}

public slots:
void showSmall()
{
parentWidget()->showMinimized();
}

void showMaxRestore()
{
if (maxNormal) {
parentWidget()->showNormal();
maxNormal = !maxNormal;
maximize->setIcon(maxPix);
} else {
parentWidget()->showMaximized();
maxNormal = !maxNormal;
maximize->setIcon(restorePix);
}
}
protected:
void mousePressEvent(QMouseEvent *me)
{
startPos = me->globalPos();
clickPos = mapToParent(me->pos());
}
void mouseMoveEvent(QMouseEvent *me)
{
if (maxNormal)
return;
parentWidget()->move(me->globalPos() - clickPos);
}

private:
QToolButton *minimize;
QToolButton *maximize;
QToolButton *close;
QPixmap restorePix, maxPix;
bool maxNormal;
QPoint startPos;
QPoint clickPos;
};

class Frame : public QFrame
{
public:

Frame()
{
m_mouse_down = false;
setFrameShape(Panel);

// Make this a borderless window which can't
// be resized or moved via the window system
setWindowFlags(Qt::FramelessWindowHint);
setMouseTracking(true);

m_titleBar = new TitleBar(this);

m_content = new QWidget(this);

QVBoxLayout *vbox = new QVBoxLayout(this);
vbox->addWidget(m_titleBar);
vbox->setMargin(0);
vbox->setSpacing(0);

QVBoxLayout *layout = new QVBoxLayout(this);
layout->addWidget(m_content);
layout->setMargin(5);
layout->setSpacing(0);
vbox->addLayout(layout);
}

// Allows you to access the content area of the frame
// where widgets and layouts can be added
QWidget *contentWidget() const { return m_content; }

TitleBar *titleBar() const { return m_titleBar; }

void mousePressEvent(QMouseEvent *e)
{
m_old_pos = e->pos();
m_mouse_down = e->button() == Qt::LeftButton;
}

void mouseMoveEvent(QMouseEvent *e)
{
int x = e->x();
int y = e->y();

if (m_mouse_down) {
int dx = x - m_old_pos.x();
int dy = y - m_old_pos.y();

QRect g = geometry();

if (left)
g.setLeft(g.left() + dx);
if (right)
g.setRight(g.right() + dx);
if (bottom)
g.setBottom(g.bottom() + dy);

setGeometry(g);

m_old_pos = QPoint(!left ? e->x() : m_old_pos.x(), e->y());
} else {
QRect r = rect();
left = qAbs(x - r.left()) <= 5;
right = qAbs(x - r.right()) <= 5;
bottom = qAbs(y - r.bottom()) <= 5;
bool hor = left | right;

if (hor && bottom) {
if (left)
setCursor(Qt::SizeBDiagCursor);
else
setCursor(Qt::SizeFDiagCursor);
} else if (hor) {
setCursor(Qt::SizeHorCursor);
} else if (bottom) {
setCursor(Qt::SizeVerCursor);
} else {
setCursor(Qt::ArrowCursor);
}
}
}

void mouseReleaseEvent(QMouseEvent *e)
{
m_mouse_down = false;
}

private:
TitleBar *m_titleBar;
QWidget *m_content;
QPoint m_old_pos;
bool m_mouse_down;
bool left, right, bottom;
};


#include "main.moc"

int main(int argc, char **argv)
{
QApplication app(argc, argv);

Frame box;
box.move(0,0);

QVBoxLayout *l = new QVBoxLayout(box.contentWidget());
l->setMargin(0);
QTextEdit *edit = new QTextEdit(box.contentWidget());
l->addWidget(edit);

box.show();
return app.exec();
}
程序运行结果:
  
  • 0
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值