简述

通过上节内容,我们实现了自定义窗体的移动,但是我们缺少一个标题栏来显示窗体的图标、标题,以及控制窗体最小化、最大化、关闭的按钮。

自定义标题栏后,所有的控件我们都可以定制,比如:在标题栏中添加换肤、设置按钮以及其他控件。

效果

自定义标题栏

实现

title_bar.h

#ifndef TITLE_BAR
#define TITLE_BAR #include <QWidget> class QLabel;
class QPushButton; class TitleBar : public QWidget
{
Q_OBJECT public:
explicit TitleBar(QWidget *parent = 0);
~TitleBar(); protected: // 双击标题栏进行界面的最大化/还原
virtual void mouseDoubleClickEvent(QMouseEvent *event); // 进行鼠界面的拖动
virtual void mousePressEvent(QMouseEvent *event); // 设置界面标题与图标
virtual bool eventFilter(QObject *obj, QEvent *event); private slots: // 进行最小化、最大化/还原、关闭操作
void onClicked(); private: // 最大化/还原
void updateMaximize(); private:
QLabel *m_pIconLabel;
QLabel *m_pTitleLabel;
QPushButton *m_pMinimizeButton;
QPushButton *m_pMaximizeButton;
QPushButton *m_pCloseButton;
}; #endif // TITLE_BAR

title_bar.cpp

#include <QLabel>
#include <QPushButton>
#include <QHBoxLayout>
#include <QEvent>
#include <QMouseEvent>
#include <QApplication>
#include "title_bar.h" #ifdef Q_OS_WIN
#pragma comment(lib, "user32.lib")
#include <qt_windows.h>
#endif TitleBar::TitleBar(QWidget *parent)
: QWidget(parent)
{
setFixedHeight(30); m_pIconLabel = new QLabel(this);
m_pTitleLabel = new QLabel(this);
m_pMinimizeButton = new QPushButton(this);
m_pMaximizeButton = new QPushButton(this);
m_pCloseButton = new QPushButton(this); m_pIconLabel->setFixedSize(20, 20);
m_pIconLabel->setScaledContents(true); m_pTitleLabel->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed); m_pMinimizeButton->setFixedSize(27, 22);
m_pMaximizeButton->setFixedSize(27, 22);
m_pCloseButton->setFixedSize(27, 22); m_pTitleLabel->setObjectName("whiteLabel");
m_pMinimizeButton->setObjectName("minimizeButton");
m_pMaximizeButton->setObjectName("maximizeButton");
m_pCloseButton->setObjectName("closeButton"); m_pMinimizeButton->setToolTip("Minimize");
m_pMaximizeButton->setToolTip("Maximize");
m_pCloseButton->setToolTip("Close"); QHBoxLayout *pLayout = new QHBoxLayout(this);
pLayout->addWidget(m_pIconLabel);
pLayout->addSpacing(5);
pLayout->addWidget(m_pTitleLabel);
pLayout->addWidget(m_pMinimizeButton);
pLayout->addWidget(m_pMaximizeButton);
pLayout->addWidget(m_pCloseButton);
pLayout->setSpacing(0);
pLayout->setContentsMargins(5, 0, 5, 0); setLayout(pLayout); connect(m_pMinimizeButton, SIGNAL(clicked(bool)), this, SLOT(onClicked()));
connect(m_pMaximizeButton, SIGNAL(clicked(bool)), this, SLOT(onClicked()));
connect(m_pCloseButton, SIGNAL(clicked(bool)), this, SLOT(onClicked()));
} TitleBar::~TitleBar()
{ } void TitleBar::mouseDoubleClickEvent(QMouseEvent *event)
{
Q_UNUSED(event); emit m_pMaximizeButton->clicked();
} void TitleBar::mousePressEvent(QMouseEvent *event)
{
#ifdef Q_OS_WIN
if (ReleaseCapture())
{
QWidget *pWindow = this->window();
if (pWindow->isTopLevel())
{
SendMessage(HWND(pWindow->winId()), WM_SYSCOMMAND, SC_MOVE + HTCAPTION, 0);
}
}
event->ignore();
#else
#endif
} bool TitleBar::eventFilter(QObject *obj, QEvent *event)
{
switch (event->type())
{
case QEvent::WindowTitleChange:
{
QWidget *pWidget = qobject_cast<QWidget *>(obj);
if (pWidget)
{
m_pTitleLabel->setText(pWidget->windowTitle());
return true;
}
}
case QEvent::WindowIconChange:
{
QWidget *pWidget = qobject_cast<QWidget *>(obj);
if (pWidget)
{
QIcon icon = pWidget->windowIcon();
m_pIconLabel->setPixmap(icon.pixmap(m_pIconLabel->size()));
return true;
}
}
case QEvent::WindowStateChange:
case QEvent::Resize:
updateMaximize();
return true;
}
return QWidget::eventFilter(obj, event);
} void TitleBar::onClicked()
{
QPushButton *pButton = qobject_cast<QPushButton *>(sender());
QWidget *pWindow = this->window();
if (pWindow->isTopLevel())
{
if (pButton == m_pMinimizeButton)
{
pWindow->showMinimized();
}
else if (pButton == m_pMaximizeButton)
{
pWindow->isMaximized() ? pWindow->showNormal() : pWindow->showMaximized();
}
else if (pButton == m_pCloseButton)
{
pWindow->close();
}
}
} void TitleBar::updateMaximize()
{
QWidget *pWindow = this->window();
if (pWindow->isTopLevel())
{
bool bMaximize = pWindow->isMaximized();
if (bMaximize)
{
m_pMaximizeButton->setToolTip(tr("Restore"));
m_pMaximizeButton->setProperty("maximizeProperty", "restore");
}
else
{
m_pMaximizeButton->setProperty("maximizeProperty", "maximize");
m_pMaximizeButton->setToolTip(tr("Maximize"));
} m_pMaximizeButton->setStyle(QApplication::style());
}
}

接口说明

  • mousePressEvent

之前,我们将界面移动的事件写在主界面里面,这会有一个问题,一般情况下,是界面随着标题栏的移动而移动,而并非界面中的所有位置都可以进行拖动,所以我们将事件写在标题栏中比较合理。

  • mouseDoubleClickEvent

双击标题栏会进行窗体的最大化/还原,所以我们需要重写此事件进行控制。

  • eventFilter

    1. 事件过滤器,这里被监听的窗体为标题栏所在的窗体,所以当窗体标题、图标等信息发生改变时,标题栏也应该随之改变。

    2. 最好不要通过直接调用接口的形式来操作对应的行为,比如:TitleBar中定义一个public函数来专门修改标题与图标,这样会造成不必要的麻烦,因为Qt本身就是基于事件的,所以此处采用过滤器的方式。

  • updateMaximize

因为窗体大小发生变化的时候,最大化的图标、提示应该对应的发生变化,所以在eventFilter中事件触发时调用。

使用方式

Widget::Widget(QWidget *parent)
: QWidget(parent)
{
setWindowFlags(Qt::FramelessWindowHint | windowFlags()); TitleBar *pTitleBar = new TitleBar(this);
installEventFilter(pTitleBar); resize(400, 300);
setWindowTitle("Custom Window");
setWindowIcon(QIcon(":/Images/logo")); QPalette pal(palette());
pal.setColor(QPalette::Background, QColor(50, 50, 50));
setAutoFillBackground(true);
setPalette(pal); QVBoxLayout *pLayout = new QVBoxLayout();
pLayout->addWidget(pTitleBar);
pLayout->addStretch();
pLayout->setSpacing(0);
pLayout->setContentsMargins(0, 0, 0, 0);
setLayout(pLayout);
}

注意

installEventFilter必须在setWindowTitle、setWindowIcon之前调用,因为必须先安装事件过滤器,相应事件触发时,才会进入标题栏的eventFilter事件中。


原文作者:一去丶二三里
作者博客:去作者博客空间

【Qt】Qt之自定义界面(添加自定义标题栏)【转】的更多相关文章

  1. ARM Linux Qt 5.x.x 无标题栏

    /********************************************************************************* * ARM Linux Qt 5. ...

  2. Qt之界面(自定义标题栏、无边框、可移动、缩放)

    效果 自定义标题栏 titleBar.h #ifndef TITLEBAR_H #define TITLEBAR_H #include <QLabel> #include <QPus ...

  3. Qt... configure: error: Qt (>= Qt 2.2.2) (headers…

    转载:http://blog.chinaunix.net/uid-23733724-id-290980.html     昨天开始在自己的fedora12下装qt~ 但是按照教程在/opt/Embed ...

  4. Qt, QT/E, Qtopia 的区别

    转自Qt, QT/E, Qtopia 的区别 Qt泛指Qt的所有桌面版本,比如Qt/X11,Qt Windows,Qt Mac等.由于Qt最早是在Linux中随着KDE流行开来的,因此通常很多人说的Q ...

  5. QT QT creator QTsdk的区别

    Qt是一个跨平台的C++图形用户界面应用程序框架.它提供给应用程序开发者建立艺术级的图形用户界面所需的所用功能.Qt是完全面向对象的,很容易扩展,并且允许真正地组件编程. QT Creator 跨平台 ...

  6. QT,QT SDK, QT Creator 区别

    Qt是一个跨平台的C++图形用户界面应用程序框架.(不仅仅是C++,还包括QML,Qquick,html5)它提供给应用程序开发者建立艺术级的图形用户界面所需的所用功能.Qt是完全面向对象的,很容易扩 ...

  7. Qt之自定义界面(添加自定义标题栏)

    简述 通过上节内容,我们实现了自定义窗体的移动,但是我们缺少一个标题栏来显示窗体的图标.标题,以及控制窗体最小化.最大化.关闭的按钮. 自定义标题栏后,所有的控件我们都可以定制,比如:在标题栏中添加换 ...

  8. Qt QML之不显示标题栏、边框

    原文连接:http://blog.csdn.net/u010780613 我使用的Qt版本是Qt 5.3.0,Qt Creator 是3.1.1. QML做界面实在太方便了,动画效果很不错. 创建一个 ...

  9. Qt之去除窗口的标题栏、通过鼠标移动窗口

    设置标题栏图标,位置与大小示例 #include<QApplication> #include<QWidget> #include<QDebug> #include ...

随机推荐

  1. iOS 修改网络图片的大小 宽和高

    //image宽和高 好用 NSString *strTemplateHTML = [NSString stringWithFormat:@"<html><head> ...

  2. Swift中if let name = optionName {}解释

    在Swift语法的if语句中,是不能出现这种情况的: let optionName = "Swift" if let name = optionName { print(" ...

  3. iOS 6编程Cookbook(影印版)

    <iOS 6编程Cookbook(影印版)> 基本信息 原书名:iOS 6 Programming Cookbook 作者: Vandad Nahavandipoor 出版社:东南大学出版 ...

  4. 上架第一个APP到苹果商店被拒绝5次

    - : Metadata Rejected (APP中的注册时跳转的 - 用户协议视图没有内容).Waiting For Review 6天  In Review 1天 第二次被拒绝 -- : Met ...

  5. Linux之zsh

    0.安装zsh: sudo apt-get install zsh git wget 1.启用zsh:chsh -s /bin/zsh 2.github: https://github.com/rob ...

  6. Ajax上传文件进度条显示

    要实现进度条的显示,就要知道两个参数,上传的大小和总文件的大小 html5提供了一个上传过程事件,在上传过程中不断触发,然后用已上传的大 小/总大小,计算上传的百分比,然后用这个百分比控制div框的显 ...

  7. ruby学习--block

    #当前块 class Block def a_method return yield if block_given? 'no block' end end obj=Block.new puts &qu ...

  8. VS2015环境下Crystal Reports(水晶报表)的安装使用

    1.首先下载Crystal Reports13对于Visual Studio 2015支持的2个文件. CRforVS_13_0_17 CRforVS_redist_install_64bit_13_ ...

  9. shell语法基础

    一.变量 1.linux大小写敏感,变量取名要注意大小写.可以通过变量名前面加$来访问变量的内容.可以通过使用read命令来将用户输入的值赋给一个变量. 2.给变量赋值时,如果字符串中包含空格,就必须 ...

  10. Linux中shell命令的用法和技巧

    使用Linux shell是我每天的基本工作,但我经常会忘记一些有用的shell命令和l技巧.当然,命令我能记住,但我不敢说能记得如何用它执行某个特定任务.于是,我开始在一个文本文件里记录这些用法,并 ...