Qt之自定义界面(添加自定义标题栏)
简述
通过上节内容,我们实现了自定义窗体的移动,但是我们缺少一个标题栏来显示窗体的图标、标题,以及控制窗体最小化、最大化、关闭的按钮。
自定义标题栏后,所有的控件我们都可以定制,比如:在标题栏中添加换肤、设置按钮以及其他控件。
效果
自定义标题栏
实现
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
事件过滤器,这里被监听的窗体为标题栏所在的窗体,所以当窗体标题、图标等信息发生改变时,标题栏也应该随之改变。
最好不要通过直接调用接口的形式来操作对应的行为,比如: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之自定义界面(添加自定义标题栏)的更多相关文章
- paip.提升用户体验---c++ qt自定义窗体(1)---标题栏的绘制
源地址:http://blog.csdn.net/attilax/article/details/12343625 paip.提升用户体验---c++ qt自定义窗体(1)---标题栏的绘制 效果图: ...
- 【Qt】Qt之自定义界面(添加自定义标题栏)【转】
简述 通过上节内容,我们实现了自定义窗体的移动,但是我们缺少一个标题栏来显示窗体的图标.标题,以及控制窗体最小化.最大化.关闭的按钮. 自定义标题栏后,所有的控件我们都可以定制,比如:在标题栏中添加换 ...
- 【Qt】Qt之自定义界面(窗体缩放-跨平台终极版)【转】
简述 通过上一节内容,我们实现了窗体的缩放,功能很不错,但是很遗憾-不支持跨平台!如果对于多平台来说,这是一个硬伤,所以,我们急需要一个能够支持跨平台的实现方案. 在网上看到过很多不同的实现方式,多多 ...
- Qt之自定义界面(窗体缩放-跨平台终极版)
简述 通过上一节内容,我们实现了窗体的缩放,功能很不错,但是很遗憾-不支持跨平台!如果对于多平台来说,这是一个硬伤,所以,我们急需要一个能够支持跨平台的实现方案. 在网上看到过很多不同的实现方式,多多 ...
- Qt之自定义界面(窗体缩放)
简述 通过前两节内容,我们实现了自定义窗体的移动,以及自定义标题栏-用来显示窗体的图标.标题,以及控制窗体最小化.最大化.关闭. 在这之后,我们还缺少窗体的缩放-当鼠标移动到窗体的边框-左.上.右.下 ...
- Qt::QWidget 无默认标题栏边框的拖拽修改大小方式
开发环境:win10+vs2015+qt5.9.1 背景:开发过程中,一般很少会使用系统提供的标题栏和边框:往往都是自定义一个自己设计的方案.这时候在QWidget中需要加上flag:Qt::Fram ...
- Qt::WindowFlags枚举类型(Qt::Widget是独立窗口和子窗口两用的,Qt::Window会有标题栏)
Qt::Widget : QWidget构造函数的默认值,如新的窗口部件没有父窗口部件,则它是一个独立的窗口,否则就是一个子窗口部件. Qt::Window : 无论是否有父窗口部件,新窗口部件都是一 ...
- 【Qt】Qt之自定义界面(QMessageBox)【转】
简述 通过前几节的自定义窗体的学习,我们可以很容易的写出一套属于自己风格的界面框架,通用于各种窗体,比如:QWidget.QDialog.QMainWindow. 大多数窗体的实现都是采用控件堆积来完 ...
- 【Qt】Qt之自定义界面(窗体缩放)【转】
简述 通过前两节内容,我们实现了自定义窗体的移动,以及自定义标题栏-用来显示窗体的图标.标题,以及控制窗体最小化.最大化.关闭. 在这之后,我们还缺少窗体的缩放-当鼠标移动到窗体的边框-左.上.右.下 ...
随机推荐
- jquery插件——图片放大器
用到了JQzoom插件,可以使图片实现放大效果
- 图片轮播插件-carouFredSel
carouFredSel图片轮播插件基于Jquery,比较常规的轮播插件,支持滚轮及键盘左右按键,加入其它插件可实现更加复杂的特效. 主页地址:http://caroufredsel.dev7stud ...
- 不借助jquery封装好的ajax,你能用js手写ajax框架吗
不借助jquery封装好的ajax,你能手写ajax框架吗?最基础的ajax框架,一起来围观吧. .创建XMLHttpRequest对象 var xhr = new XMLHttpRequest(); ...
- 解决Maven默认仓库没有的jar下载(二)
前言: 在 “解决Maven不能下载“oracle.aspectjweaver.com.springsource.net.sf.cglib”jar(http://www.cnblogs.com/wql ...
- 【BZOJ】【3196】Tyvj 1730 二逼平衡树
树套树 Orz zyf 学(co)习(py)了一下树套树的写法,嗯……就是线段树套平衡树. 具体实现思路就是:外部查询用的都是线段树,查询内部自己调用平衡树的操作. 抄抄代码有助理解= = 八中挂了… ...
- nodeJS实战
github代码托管地址: https://github.com/Iwillknow/microblog.git 根据<NodeJS开发指南>实例进行实战{{%并且希望一步步自己能够逐步将 ...
- 【WCF--初入江湖】12 WCF与Ajax编程
12 WCF与Ajax编程 Ajax Ajax基本原理 AJAX技术的本质原理就是:使用 JavaScript 的 XMLHttpRequest 对象来直接与服务器进行通信. 通过这个对象,JavaS ...
- Python-aiohttp百万并发
http://www.aikaiyuan.com/10935.html 本文将测试python aiohttp的极限,同时测试其性能表现,以分钟发起请求数作为指标.大家都知道,当应用到网络操作时,异步 ...
- Struts 2知识回顾----拦截器(Intercept)总结
什么是Struts 2拦截器? 从软件构架上来说,拦截器是实现了面向方面编程的组件.它将影响了多个业务对象的公共行为封装到一个个可重用的模块,减少了系统的重复代码,实现功能的高度内聚,确保了业务对象的 ...
- javascript 在一个函数参数中包含另一个函数的引用
javascript函数的参数包含另一个函数的情形: <script> //b函数的参数func为另一个函数 function b(a, func) { alert(a); //调用参数 ...