简述

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

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

效果

自定义标题栏

实现

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之自定义界面(添加自定义标题栏)的更多相关文章

  1. paip.提升用户体验---c++ qt自定义窗体(1)---标题栏的绘制

    源地址:http://blog.csdn.net/attilax/article/details/12343625 paip.提升用户体验---c++ qt自定义窗体(1)---标题栏的绘制 效果图: ...

  2. 【Qt】Qt之自定义界面(添加自定义标题栏)【转】

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

  3. 【Qt】Qt之自定义界面(窗体缩放-跨平台终极版)【转】

    简述 通过上一节内容,我们实现了窗体的缩放,功能很不错,但是很遗憾-不支持跨平台!如果对于多平台来说,这是一个硬伤,所以,我们急需要一个能够支持跨平台的实现方案. 在网上看到过很多不同的实现方式,多多 ...

  4. Qt之自定义界面(窗体缩放-跨平台终极版)

    简述 通过上一节内容,我们实现了窗体的缩放,功能很不错,但是很遗憾-不支持跨平台!如果对于多平台来说,这是一个硬伤,所以,我们急需要一个能够支持跨平台的实现方案. 在网上看到过很多不同的实现方式,多多 ...

  5. Qt之自定义界面(窗体缩放)

    简述 通过前两节内容,我们实现了自定义窗体的移动,以及自定义标题栏-用来显示窗体的图标.标题,以及控制窗体最小化.最大化.关闭. 在这之后,我们还缺少窗体的缩放-当鼠标移动到窗体的边框-左.上.右.下 ...

  6. Qt::QWidget 无默认标题栏边框的拖拽修改大小方式

    开发环境:win10+vs2015+qt5.9.1 背景:开发过程中,一般很少会使用系统提供的标题栏和边框:往往都是自定义一个自己设计的方案.这时候在QWidget中需要加上flag:Qt::Fram ...

  7. Qt::WindowFlags枚举类型(Qt::Widget是独立窗口和子窗口两用的,Qt::Window会有标题栏)

    Qt::Widget : QWidget构造函数的默认值,如新的窗口部件没有父窗口部件,则它是一个独立的窗口,否则就是一个子窗口部件. Qt::Window : 无论是否有父窗口部件,新窗口部件都是一 ...

  8. 【Qt】Qt之自定义界面(QMessageBox)【转】

    简述 通过前几节的自定义窗体的学习,我们可以很容易的写出一套属于自己风格的界面框架,通用于各种窗体,比如:QWidget.QDialog.QMainWindow. 大多数窗体的实现都是采用控件堆积来完 ...

  9. 【Qt】Qt之自定义界面(窗体缩放)【转】

    简述 通过前两节内容,我们实现了自定义窗体的移动,以及自定义标题栏-用来显示窗体的图标.标题,以及控制窗体最小化.最大化.关闭. 在这之后,我们还缺少窗体的缩放-当鼠标移动到窗体的边框-左.上.右.下 ...

随机推荐

  1. OC面向对象封装

    面向对象语言的三大特性:封装.继承.多态 封装:不暴露自己类的内部的属性,提高自己的数据的安全性:就像一个接线盒一样,内部结构看不到,只有外部的接口提供给我们使用,这样既安全又美观:在代码方面就是结构 ...

  2. 好项目烂架构的问题,四年coder的吐槽

    四年多码农,毕业后在一家小私企做前端:(初始asp.net,对oo有了比较深切的理解:处于对某空间的效仿,对前端技术架构理解的比较透彻): 在这家公司混了4个月之后跳出来想自己单干: 自己接了个小项目 ...

  3. 仅仅测试Word2016发布博客

    我来啦! 我走啦!     哈哈哈!   int main(int argc, char *argv[]) {     int mysocket; //建立一个socket后返回的值是int类型的. ...

  4. shell uniq sort -u 去重排序

    sort -u 和 uniq都能起到删除重复信息的功能,那么他们的区别究竟在哪呢? $ cat test jason jason jason fffff jason 下面分别执行三个命令 :sort ...

  5. ASP.NET MVC 中CSS JS压缩合并 功能的使用方法

    通过压缩合并js文件和css文件,可以减少 服务器的响应 次数和 流量,可以大大减小服务器的压力,对网站优化有比较明显的帮助!压缩合并 css 文件和js文件是网站优化的一个 比较常用的方法. ASP ...

  6. Introduction To Monte Carlo Methods

    Introduction To Monte Carlo Methods I’m going to keep this tutorial light on math, because the goal ...

  7. uva 10912

    dp 记忆化搜索 #include <cstdio> #include <cstdlib> #include <cmath> #include <map> ...

  8. javax.mail.MessagingException: 501 Syntax: HELO hostname Linux端异常解决

    在项目里面使用javamail在window环境正常,放在服务器上面的时候抛出异常javax.mail.MessagingException: 501 Syntax: HELO hostname ,原 ...

  9. 【转】12 款优秀的 JavaScript MVC 框架评估

    JavaScript MVC 框架有很多,不同框架适合于不同项目需求.了解各种框架的性能及优劣有利于我们更加快捷的开发.作者(Gordon L.Hempton)一直在寻求哪种MVC框架最为完美,他将目 ...

  10. iOS 开发--github的demo

    令人惊讶的是,YYText 虽然代码量很大(超过一万行),但它只是 ibireme 的作品之一.ibireme 利用业余时间完成了 YYKit 工具库,包括: YYModel — 高性能的 iOS J ...