Qt窗口的标题栏自绘

因个人需要,要修改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();
}

转载地址:http://blog.csdn.net/litterflybug/article/details/4157482

时间: 2024-10-11 08:32:05

Qt窗口的标题栏自绘的相关文章

自定义QT窗口部件外观之QStyle

自定义QT窗口部件外观 重新定义Qt内置窗口部件的外观常用的方法有两种:一是通过子类化QStyle 类或者预定义的一个样式,例如QWindowStyle,来定制应用程序的观感:二是使用Qt样式表. QStyle 类的使用 1.      准备必要的背景图片.在你想添加自定义风格的工程目录下新建一个文件夹“images”,将背景图片等放入文件夹“images”. 2.      点击Qt Creator的“文件”->“新建文件或工程”->模板选择“Qt”,再选择Qt资源文件->点击“选择”

Qt窗口定制

qt中的QWidget窗口支持窗体绘制,但是不支持窗口标题栏绘制,想要美观的界面,还需要自己去定制,下面我就介绍一种定制窗体的方法 一个窗口无非就3部分,标题栏.窗体和状态栏,接下来我定制的窗口没有状态栏,如果自己想加状态栏的话,照着这个模式自己也可以添加,说白了,窗口定制就是把完整的窗口分3部分定制,而每个部分又都是一个qt窗口 定制窗口效果图如下,根据个人喜好,自己也可以定制不同的效果 图1 定制窗口 如图1所示,这个窗口包含两部分,标题栏和窗体,这两部分其实分别是一个没有标题栏的QWidg

[DForm]我也来做自定义Winform之另类标题栏重绘

据说得有楔子 按照惯例,先来几张样例图(注:为了展示窗口阴影效果,截图范围向外扩展了些,各位凭想象吧).                   还要来个序 其实,很多年没写过Winform了,前端时间在重构我们公司自己的呼叫中心系统,突然就觉得客户端好丑好丑,对于我这种强迫症晚期患者来说,界面不好看都不知道怎么写代码的,简直就是种折磨,还是满清十大酷刑级别那种. 很多人推荐WPF,不过个人对WPF没啥感觉,而且据说也无法支持2.0,还是采用Winform技术来搞吧. 终于第一节 做Winform皮

Qt窗口及控件-窗口Close()自动释放

在进行一个四窗口项目,当第四个窗口显示结果后,若重新开始则close()结果页面后new第一个窗口 发现不断的重新开始会导致内存占用越来越多 Qt窗口在Close()指令后调用CloseEven(),最后判断是否关闭 若关闭,则Hide()窗口,并不是真正的释放内存.若不关闭则不作任何操作 此时给窗口增加如下设置: setAttribute(Qt::WA_DeleteOnClose); 可实现窗口在Close()后自动释放内存

深度探索QT窗口系统(五篇)

窗口作为界面编程中最重要的部分,没有窗口就没有界面,是窗口让我们摆脱了DOS时代,按钮是一个窗口,文本框是一个窗口,标签页是一个窗口,...一个窗口可以由多个窗口组成,每天我们都在与窗口打交道,当你打开windows时,桌面就是一个窗口,你打开浏览器时,你也正在访问窗口...好了,回到今天的话题,QT窗口系统,QT是一个跨平台的框架,类似微软的MFC,Borland的OWL,前者只适用于windows,而使用QT你可以开发windows平台应用程序,你也可以开发linux应用程序,当然了你也可以

CentOS下Qt窗口透明效果失效,成黑色背景的问题

一.问题 Linux系统下Qt窗口的透明效果成了黑色,但同样的代码在windows机子上有透明效果,主要是修改系统的配置,仅在centos6.3及其以上版本实验过.其他系统可以相应配置. 二.问题运行图 (1)Qt透明效果,centos下运行都会出现如下图1所示. 三.解决方法 (1)窗口透明,窗口上的控件不透明,其代码设置 [html] view plain copy setAutoFillBackground(false);  //这个不设置的话就背景变黑 setWindowFlags(Qt

QT窗口置顶/真透明/背景模糊/非矩形/跳过任务栏分页器/无边框/无焦点点击/焦点穿透

qt 窗口置顶/真透明/背景模糊/非矩形/跳过任务栏分页器/无边框/无焦点点击/焦点穿透 窗口置顶qt 里是 setWindowFlags(Qt::WindowStaysOnTopHint)kde 里是 KWindowSystem::setState(winId(), NET::KeepAbove)这样的置顶窗口不会处于全屏窗口的上方,如果需要真正的置顶,setWindowFlags(Qt::X11BypassWindowManagerHint) 可无视这个规则,但这样不会出现任务栏等,kimt

qt 窗口控件自动调整大小

/******************************************************************** * qt 窗口控件自动调整大小 * * 在写gui的时候,希望窗口能够自动调整大小,这样就不许要手动调整. * qt creator中就集成了这种方法,在qt中设置即可. * 本文参考链接: * http://www.cnblogs.com/emouse/archive/2013/05/19/3087708.html * * Tony, 2016-5-21,

QT 隐藏qdockwidget标题栏 偏方

QT 隐藏qdockwidget标题栏 偏方 的确没有正确的方法,不过这个非常凑效 I'm using Qt v4.3.2, and had the same problem and discovered that calling setTitleBarWidget(0) is NOT sufficient to remove the title bar and free up the client window space when the widget is DOCKED. This is