怎樣控制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();
}
程序運行結果:
  
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章