-
2021-12-09 16:30:04
Qt自定义标题栏,实现拖动功能
提示:这里可以添加系列文章的所有文章的目录,目录需要自己手动添加
例如:第一章 Python 机器学习入门之pandas的使用
提示:写完文章后,目录可以自动生成,如何生成可参考右边的帮助文档
前言
Qt自定义标题栏,实现拖动功能
一、MyTitle继承于QWidget的实现
class Mytitile : public QWidget
二、关键代码
1.重载
重载以下三个方法:
protected: void mousePressEvent(QMouseEvent* event) Q_DECL_OVERRIDE; void mouseReleaseEvent(QMouseEvent* event) Q_DECL_OVERRIDE; void mouseMoveEvent(QMouseEvent* event) Q_DECL_OVERRIDE; private: QPoint mouse_press_, mouse_move_; bool mouse_left_pressed_;
2.实现
代码如下:
void Mytitile ::mousePressEvent(QMouseEvent* event) { if (event->button() == Qt::LeftButton) { mouse_press_= event->globalPos(); mouse_left_pressed_= true; } event->ignore();//表示继续向下传递事件,其他的控件还可以去获取 } void Mytitile ::mouseReleaseEvent(QMouseEvent* event) { if (event->button() == Qt::LeftButton) { mouse_left_pressed_= false; } event->ignore(); } void Mytitile ::mouseMoveEvent(QMouseEvent* event) { if (leftBtnClk) { mouse_move_= event->globalPos(); this->window()->move(this->window()->pos() + mouse_move_ - mouse_press_); //移动window,这样就不需要在页面的类中去重载这三个函数了,所有添加了这个title的页面都可拖动。 mouse_press_= mouse_move_; //每次拖动都设置好press的位置,这样下一次触发拖动才能正确 } event->ignore(); }
3.使用
一般在Qt的Designer模式里给页面加一个Mytitle,添加方法:拖入一个Widget,设置合理的大小以及位置,并提升成Mytitle。
提升控件的方法,右击该控件->提升为…->输入刚刚的类名->点击添加按钮->选中刚刚的类型->点击提升按钮。
总结
完事儿。
更多相关内容 -
QT自定义标题栏最大最小化关闭按钮
2019-11-21 08:49:32QT自定义标题栏最大最小化关闭按钮源码,专给入门者参考源码 QT5,VS2017,窗口背景贴图按钮贴图 -
qt自定义标题栏 已封装
2020-08-10 10:14:29初学者项目需要,自己封装的一个qt自定义标题栏,可以直接调用。环境是vs2013+qt5.6.2,其他环境我也不知道能否使用,谨慎下载。 大部分标题栏的显示效果都放在paintEvent函数中,可以动态更改。大部分效果都写了... -
Qt自定义标题栏
2021-09-19 13:52:17Qt自定义标题栏效果图源码使用方法实现思路及部分代码参考 效果图 1.设置为无边框窗口后拉伸、移动、放大缩小等事件需要自己重新实现,我只实现标题栏拖动、双击放大/还原、窗体边缘可拉伸等基本功能,有其他需求的...效果图
1.设置为无边框窗口后拉伸、移动、放大缩小等事件需要自己重新实现,我只实现标题栏拖动、双击放大/还原、窗体边缘可拉伸等基本功能,有其他需求的小伙伴可参考和修改源码
2.拉伸右、下、右下这三个方向不会抖动,拉伸其他方向均会抖动,貌似很多自定义窗口的软件都是这样,包括微软的Edge浏览器、QQ、网易云音乐等
3.事件实现看过很多别人的方法,思路都是差不多的,但仅实现放大、缩小、移动、拉伸的话,很多人的代码都写得过于复杂,不便于我这种菜鸡阅读和理解。我的代码中拉伸实现主要参考了qt 无边框窗口,可拖动,可拉伸 这篇文章
4.试过刘典武大佬的无抖动方案源码,一样是会抖动的,相对来说没那么抖
Qt开源作品38-无边框窗体方案(无抖动,支持win、linux、mac等系统,侧边半屏顶部全屏)
源码
链接: https://pan.baidu.com/s/1HtN-ciYU_-HaVTId6gjMKw
提取码: 5dmy使用方法
- 将 titlebar.h,titlebar.cpp,titlebar.ui 文件加入到自己的项目中
- 包含头文件 #include "titlebar.h"
- 创建标题栏对象 TitleBar title;
- 创建主窗口对象 QWidget w;
- 调用函数将主窗口添加入标题栏窗口 title.setMainWidget(&w);
- 调用显示函数 title.show();
- 2021.10.21注:如果实例化的是普通对象,则3和4顺序不可倒换,因为title.setMainWidget(&w)是title把w作为子对象,构造时应先构造title再构造w,析构时先析构w再析构title。如果顺序倒换,则先析构了title,这时再析构w就会报错。如果创建的是对象指针则实例化顺序不影响
实现思路及部分代码
声明
#ifndef TITLEBAR_H #define TITLEBAR_H #include <QWidget> #include <QMouseEvent> #include <QPoint> QT_BEGIN_NAMESPACE namespace Ui { class TitleBar; } QT_END_NAMESPACE class TitleBar : public QWidget { Q_OBJECT public: TitleBar(QWidget *parent = nullptr); ~TitleBar(); /** * @brief msetStyleSheet 通过文件设置全局样式 * @param styleSheet css/qss等样式文件 */ static void msetStyleSheet(const QString &styleSheet); /** * @brief setMainWidget 设置主窗口 * @param widget 窗口指针 */ void setMainWidget(QWidget *widget); /** * @brief setTitleBarText 设置标题 * @param text 文本 */ void setTitleBarText(const QString &text); /** * @brief setTitleBarIcon 设置标题栏图标 * @param icon 图标 */ void setTitleBarIcon(const QString &icon); /** * @brief setTitleBarStyleSheet 设置标题栏样式 * @param sheet 样式 */ void setTitleBarStyleSheet(const QString &sheet); /** * @brief setTitleBarBackGround 设置标题栏背景颜色 * @param r 红色值 * @param g 绿色值 * @param b 蓝色值 */ void setTitleBarBackGround(const int &r, const int &g, const int &b); /** * @brief setTitleTextFont 设置标题栏字体 * @param font 字体样式 */ void setTitleTextFont(const QFont &font); /** * @brief setMarginSize 设置拉伸边距 * @param size 边距值 */ void setMarginSize(const int &size); /** * @brief The MousePosition enum 鼠标区域枚举 * 左上角(1,1) 上(1,2) 右上角(1,3) * 左(2,1) 中(2,2) 右(2,3) * 左下角(3,1) 下(3,2) 右下角(3,3) */ enum MousePosition { PosLeftTop = 11, PosTop = 12, PosRightTop = 13, PosLeft = 21, PosMid = 22, PosRight = 23, PosLeftBottom = 31, PosBottom = 32, PosRightBottom = 33, }; protected: bool eventFilter(QObject *watched, QEvent *event) override; void mousePressEvent(QMouseEvent *event) override; void mouseMoveEvent(QMouseEvent *event) override; void mouseReleaseEvent(QMouseEvent *event) override; /** * @brief getMouseArea 获取鼠标所在区域 * @param pos 全局坐标 * @return */ int getMouseArea(const QPoint &pos); /** * @brief setMouseCursor 设置鼠标样式 * @param pos 全局坐标 */ void setMouseCursor(const QPoint &pos); private: Ui::TitleBar *ui; QWidget *mainWidget;//主窗口指针 QPoint dragPos;//窗口拖动位置 bool isMoveEvent;//标题栏移动事件标志 QPoint lastPos;//左键按下时停留的坐标 bool leftBtnPress;//左键按下标志 int mousePressArea; //鼠标点击的区域 int marginSize;//边缘边距值 bool isMidArea;//在非边缘区域标志 int minWidth;//窗体(可缩小至)宽度 int minHeight;//窗体(可缩小至)高度 }; #endif // TITLEBAR_H
1. 窗体布局
以一个Widget作为整体窗口,在此基础上添加一个Widget作为标题栏,然后提供一个添加主窗口的接口函数 setMainWidget,布局属性边距、垂直策略那些啥的在ui文件里设置了
void TitleBar::setMainWidget(QWidget *widget) { if (widget != nullptr) { mainWidget = widget; mainWidget->setParent(this); mainWidget->show(); mainWidget->installEventFilter(this); //重新布局标题栏和窗口 QLayout *mainLayout = this->layout(); mainLayout->removeWidget(ui->titleWidget); mainLayout->addWidget(ui->titleWidget); mainLayout->addWidget(mainWidget); } }
2. 标题栏拖动窗口及双击最大化
用事件过滤器限定窗口整体拖动只在标题栏事件中
窗口拖动应该不难,偏移量就是左键按下时鼠标的位置相对于整体窗口的左上角的位置
双击放大就没啥好说了,但是会和拖动冲突,现象就是双击放大后窗口移动到了鼠标的位置,所以用isMoveEvent这个标志来解决冲突bool TitleBar::eventFilter(QObject *watched, QEvent *event) { //标题栏区域事件 if (isMidArea && watched == ui->titleWidget) { setCursor(Qt::ArrowCursor); QMouseEvent *mouseEvent = static_cast<QMouseEvent*>(event); switch (event->type()) { case QEvent::MouseButtonPress: dragPos = mouseEvent->globalPos() - frameGeometry().topLeft();//计算偏移量 isMoveEvent = true; break; case QEvent::MouseButtonDblClick: isMoveEvent = false; emit ui->btnMax->clicked(); break; case QEvent::MouseMove: if (isMoveEvent && !isMaximized()) move(mouseEvent->globalPos() - dragPos);//移动窗口 break; case QEvent::MouseButtonRelease: isMoveEvent = false; break; default: break; } } //主窗口区域事件 if (isMidArea && watched == mainWidget) setCursor(Qt::ArrowCursor); return QWidget::eventFilter(watched, event); }
3. 光标样式及拉伸动作
3.1. 光标样式
上图把整体窗口分为了9个区域,光标在哪个区域就根据图上的划分计算(函数getMouseArea),得出区域值后便根据区域值对应的区域设置光标(函数setMouseCursor),在mouseMoveEvent中调用setMouseCursor
区域枚举值/** * @brief The MousePosition enum 鼠标区域枚举 * 左上角(1,1) 上(1,2) 右上角(1,3) * 左(2,1) 中(2,2) 右(2,3) * 左下角(3,1) 下(3,2) 右下角(3,3) */ enum MousePosition { PosLeftTop = 11, PosTop = 12, PosRightTop = 13, PosLeft = 21, PosMid = 22, PosRight = 23, PosLeftBottom = 31, PosBottom = 32, PosRightBottom = 33, };
int TitleBar::getMouseArea(const QPoint &pos) { int posX = pos.x();//全局x坐标 int posY = pos.y();//全局y坐标 int mainWidth = width();//全局宽度 int mainHeight = height();//全局高度 int areaX = 0;//x所在区域 int areaY = 0;//y所在区域 //判断x所在区域 if (posX > (mainWidth - marginSize)) areaX = 3; else if (posX < marginSize) areaX = 1; else areaX = 2; //判断y所在区域 if (posY > (mainHeight - marginSize)) areaY = 3; else if (posY < marginSize) areaY = 1; else areaY = 2; //返回区域值,如区域1:1 + 1*10 = 11 return areaX + areaY*10; } void TitleBar::setMouseCursor(const QPoint &pos) { Qt::CursorShape cursor; //获取区域值 int area = getMouseArea(pos); switch (area) { case PosLeftTop: case PosRightBottom: cursor = Qt::SizeFDiagCursor; break; case PosRightTop: case PosLeftBottom: cursor = Qt::SizeBDiagCursor; break; case PosLeft: case PosRight: cursor = Qt::SizeHorCursor; break; case PosTop: case PosBottom: cursor = Qt::SizeVerCursor; break; case PosMid: cursor = Qt::ArrowCursor; break; default: break; } setCursor(cursor); }
3.2. 拉伸动作
重点在重写mouseMoveEvent函数,核心在switch语句中,根据光标所在区域以及偏移量进行运算,条件判断用于防止过度拉伸,理解代码时可不看void TitleBar::mousePressEvent(QMouseEvent *event) { if (event->button() == Qt::LeftButton) { leftBtnPress = true;//左键按下标志 lastPos = event->globalPos();//按下时鼠标坐标 mousePressArea = getMouseArea(event->pos());//按下时鼠标所在区域 } return QWidget::mousePressEvent(event); } void TitleBar::mouseMoveEvent(QMouseEvent *event) { //最大化状态时不能拉伸 if (isMaximized()) return; //根据位置设置鼠标样式 if (!leftBtnPress) setMouseCursor(event->pos()); if (leftBtnPress && (event->buttons() & Qt::LeftButton)) { if (mousePressArea != PosMid) isMidArea = false; QPoint offset = event->globalPos() - lastPos;//偏移量=当前鼠标坐标-按下时鼠标坐标 int offsetX = offset.x(); int offsetY = offset.y(); QRect globalGeometry = frameGeometry();//获取窗口矩形 int globalWidth = globalGeometry.width(); int globalHeight = globalGeometry.height(); //拉伸后位置=当前位置+偏移量 //加入条件判断防止过度拉伸 switch (mousePressArea) { case PosLeftTop: if (minWidth <= (globalWidth - offsetX)) globalGeometry.setLeft(globalGeometry.left() + offsetX); if (minHeight <= (globalHeight - offsetY)) globalGeometry.setTop(globalGeometry.top() + offsetY); //globalGeometry.setTopLeft(globalGeometry.topLeft() + offset); break; case PosTop: if (minHeight <= (globalHeight - offsetY)) globalGeometry.setTop(globalGeometry.top() + offsetY); break; case PosRightTop: if (minWidth <= (globalWidth + offsetX)) globalGeometry.setRight(globalGeometry.right() + offsetX); if (minHeight <= (globalHeight - offsetY)) globalGeometry.setTop(globalGeometry.top() + offsetY); //globalGeometry.setTopRight(globalGeometry.topRight() + offset); break; case PosRight: if (minWidth <= (globalWidth + offsetX)) globalGeometry.setRight(globalGeometry.right() + offsetX); break; case PosRightBottom: if (minWidth <= (globalWidth + offsetX)) globalGeometry.setRight(globalGeometry.right() + offsetX); if (minHeight <= globalHeight + offsetY) globalGeometry.setBottom(globalGeometry.bottom() + offsetY); //globalGeometry.setBottomRight(globalGeometry.bottomRight() + offset); break; case PosBottom: if (minHeight <= (globalHeight + offsetY)) globalGeometry.setBottom(globalGeometry.bottom() + offsetY); break; case PosLeftBottom: if (minWidth <= (globalWidth - offsetX)) globalGeometry.setLeft(globalGeometry.left() + offsetX); if (minHeight <= (globalHeight + offsetY)) globalGeometry.setBottom(globalGeometry.bottom() + offsetY); //globalGeometry.setBottomLeft(globalGeometry.bottomLeft() + offset); break; case PosLeft: if (minWidth <= (globalWidth - offsetX)) globalGeometry.setLeft(globalGeometry.left() + offsetX); break; default: break; } //设置拉伸后坐标并记录 setGeometry(globalGeometry); lastPos = event->globalPos(); } return QWidget::mouseMoveEvent(event); } void TitleBar::mouseReleaseEvent(QMouseEvent *event) { leftBtnPress = false;//左键释放 isMidArea = true; setCursor(Qt::ArrowCursor); return QWidget::mouseReleaseEvent(event); }
4. 其他接口函数声明/** * @brief msetStyleSheet 通过文件设置全局样式 * @param styleSheet css/qss等样式文件 */ static void msetStyleSheet(const QString &styleSheet); /** * @brief setMainWidget 设置主窗口 * @param widget 窗口指针 */ void setMainWidget(QWidget *widget); /** * @brief setTitleBarText 设置标题 * @param text 文本 */ void setTitleBarText(const QString &text); /** * @brief setTitleBarIcon 设置标题栏图标 * @param icon 图标 */ void setTitleBarIcon(const QString &icon); /** * @brief setTitleBarStyleSheet 设置标题栏样式 * @param sheet 样式 */ void setTitleBarStyleSheet(const QString &sheet); /** * @brief setTitleBarBackGround 设置标题栏背景颜色 * @param r 红色值 * @param g 绿色值 * @param b 蓝色值 */ void setTitleBarBackGround(const int &r, const int &g, const int &b); /** * @brief setTitleTextFont 设置标题栏字体 * @param font 字体样式 */ void setTitleTextFont(const QFont &font); /** * @brief setMarginSize 设置拉伸边距 * @param size 边距值 */ void setMarginSize(const int &size);
参考
[1]: qt 无边框窗口,可拖动,可拉伸
[2]: qt 无边框窗体拖动、拉伸 -
QT快速开发自定义标题栏示例
2020-10-08 11:14:03QT快速开发自定义标题栏示例,非常简单,使用方法如下: 1、目标窗口添加标题栏、最大化最小化关闭按钮(该步最好每次使用时,从模板程序中直接复制) 2、窗口基类从QDialog改为QFramelessDialog 3、窗口构造函数中... -
Hello Qt——Qt自定义标题栏
2022-03-01 22:42:10一、Qt自定义标题栏简介 QWidget及其子类窗体组件的标题栏受操作系统的控制,即标题栏的界面风格与操作系统的主题风格相同,工程实践中需要开发者自行定义,达到美化应用程序界面的目的。 二、Qt自定义标题栏实现 ...一、Qt自定义标题栏简介
QWidget及其子类窗体组件的标题栏受操作系统的控制,即标题栏的界面风格与操作系统的主题风格相同,工程实践中需要开发者自行定义,达到美化应用程序界面的目的。
二、Qt自定义标题栏实现
1、自定义标题栏的功能
自定义标题栏需要完成功能如下:
(1)自定义标题栏需要包含最小化按钮、最大化按钮、关闭按钮、标题标签、图标标签等图形元素。
(2)标题栏的拖拽。
(3)鼠标双击标题栏实现窗体的最大化、最小化。
2、自定义标题栏的界面布局
自定义标题栏的界面布局如下:
3、标题栏拖拽功能的实现
窗体的拖拽平移过程如下图:
当鼠标在窗体的标题栏按下并移动时,窗体会按照鼠标移动的轨迹进行平移。因此,窗体每次移动都是在当前位置按照鼠标移动的矢量进行移动。标题栏拖拽功能的实现需要实现mousePressEvent、mouseMoveEvent、mouseReleaseEvent三个事件处理函数。
MouseEvent中的globalPos()函数返回的是相对屏幕的位置坐标,而pos()则是返回鼠标在当前控件(即捕获该鼠标事件的控件)中的位置。
QWidget窗体的geometry().topLeft()则返回的是当前窗体的左上角在屏幕中的位置。startPos = event->globalPos();// 鼠标的全局初始位置,按下时记住 curWindowPos = geometry().topleft();// 窗体的全局位置,移动时 endPos = event->globalPos();// 鼠标按下发生移动之后的位置,移动时 move(curWindowPos+(startPos-endPos));// 根据矢量移动方向是初始位置减去末位置,移动时 startPos = endPos;// 将初始位置记为上次末位置,然后执行直到释放拖拽,移动时
实现代码如下:
void TitleBar::mousePressEvent(QMouseEvent *event) { // 鼠标左键按下事件 if (event->button() == Qt::LeftButton) { // 记录鼠标左键状态 m_leftButtonPressed = true; //记录鼠标在屏幕中的位置 m_start = event->globalPos(); } } void TitleBar::mouseMoveEvent(QMouseEvent *event) { // 持续按住才做对应事件 if(m_leftButtonPressed) { //将父窗体移动到父窗体原来的位置加上鼠标移动的位置:event->globalPos()-m_start parentWidget()->move(parentWidget()->geometry().topLeft() + event->globalPos() - m_start); //将鼠标在屏幕中的位置替换为新的位置 m_start = event->globalPos(); } } void TitleBar::mouseReleaseEvent(QMouseEvent *event) { // 鼠标左键释放 if (event->button() == Qt::LeftButton) { // 记录鼠标状态 m_leftButtonPressed = false; } }
4、标题栏双击实现最大化、最小化
鼠标双击事件处理函数mouseDoubleClickEvent实现如下:
void TitleBar::mouseDoubleClickEvent(QMouseEvent *event) { m_maximizeButton->click(); }
最大化、最小化、关闭按钮的槽函数如下:
void TitleBar::onClicked() { QPushButton *pButton = qobject_cast<QPushButton *>(sender()); QWidget *pWindow = this->window(); if (pWindow->isTopLevel()) { if (pButton == m_minimizeButton) { pWindow->showMinimized(); } else if (pButton == m_maximizeButton) { pWindow->isMaximized() ? pWindow->showNormal() : pWindow->showMaximized(); } else if (pButton == m_closeButton) { pWindow->close(); } } }
三、Qt自定义窗体基类示例
1、自定义窗体基类的功能
自定义窗体基类的功能如下:
(1)自定义标题栏。
(2)增加内容组件,内容组件内部的界面布局完全由具体的用户决定。
2、自定义窗体基类的实现
TitleBar.h文件:
#ifndef TITLEBAR_H #define TITLEBAR_H #include <QWidget> #include <QPushButton> #include <QLabel> #include <QHBoxLayout> #include <QEvent> #include <QMouseEvent> #include <QApplication> #include <QPoint> #include <QPixmap> #include <QString> /** * @brief 标题栏界面组件 * @author */ class TitleBar : public QWidget { Q_OBJECT public: explicit TitleBar(QWidget *parent = NULL); /** * @brief 设置标题栏标题 * @param title,参数,设置的标题 */ void setWindowTitle(const QString& title); /** * @brief 设置标题栏的图标 * @param iconPath,参数,图标的路径 */ void SetTitleBarIcon(const QString& iconPath); protected: /** * @brief 鼠标双击事件处理函数 * @param event,参数,事件 * @note 双击标题栏进行界面的最大化/还原 */ virtual void mouseDoubleClickEvent(QMouseEvent *event); /** * @brief 鼠标按下事件处理函数 * @param event,参数,事件 * @note 按下鼠标左键 */ virtual void mousePressEvent(QMouseEvent *event); /** * @brief 鼠标移动事件处理函数 * @param event,参数,事件 * @note 移动鼠标 */ virtual void mouseMoveEvent(QMouseEvent *event); /** * @brief 鼠标释放事件处理函数 * @param event,参数,事件 * @note 释放鼠标 */ virtual void mouseReleaseEvent(QMouseEvent *event); /** * @brief 事件过滤处理器 * @param obj,参数 * @param event,参数,事件 * @return 成功返回true,失败返回false * @note 设置标题、图标 */ virtual bool eventFilter(QObject *obj, QEvent *event); /** * @brief 最大化/还原 */ void updateMaximize(); protected slots: /** * @brief 最小化、最大化/还原、关闭按钮点击时响应的槽函数 */ void onClicked(); private: QLabel* m_iconLabel; QLabel* m_titleLabel; QPushButton* m_minimizeButton; QPushButton* m_maximizeButton; QPushButton* m_closeButton; QPoint m_start;//起始点 QPoint m_end;//结束点 bool m_leftButtonPressed;//鼠标左键按下标记 }; #endif // TITLEBAR_H
TitleBar.cpp文件:
#include "TitleBar.h" TitleBar::TitleBar(QWidget *parent) : QWidget(parent) { setFixedHeight(30); setWindowFlags(Qt::FramelessWindowHint); m_iconLabel = new QLabel(this); m_iconLabel->setFixedSize(20, 20); m_iconLabel->setScaledContents(true); m_titleLabel = new QLabel(this); m_titleLabel->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed); m_minimizeButton = new QPushButton(this); m_minimizeButton->setFixedSize(27, 22); m_minimizeButton->setObjectName("minimizeButton"); m_maximizeButton = new QPushButton(this); m_maximizeButton->setFixedSize(27, 22); m_maximizeButton->setObjectName("maximizeButton"); m_closeButton = new QPushButton(this); m_closeButton->setFixedSize(27, 22); m_closeButton->setObjectName("closeButton"); QHBoxLayout* layout = new QHBoxLayout; layout->addWidget(m_iconLabel); layout->addStretch(1); layout->addWidget(m_titleLabel); layout->addStretch(1); layout->addWidget(m_minimizeButton); layout->addWidget(m_maximizeButton); layout->addWidget(m_closeButton); setLayout(layout); setProperty("titleBar", true); setObjectName("titleBar"); connect(m_minimizeButton, SIGNAL(clicked(bool)), this, SLOT(onClicked())); connect(m_maximizeButton, SIGNAL(clicked(bool)), this, SLOT(onClicked())); connect(m_closeButton, SIGNAL(clicked(bool)), this, SLOT(onClicked())); } void TitleBar::setWindowTitle(const QString &title) { m_titleLabel->setAlignment(Qt::AlignCenter); m_titleLabel->setText(title); } void TitleBar::SetTitleBarIcon(const QString &iconPath) { QPixmap map(iconPath); m_iconLabel->setPixmap(map); } void TitleBar::mouseDoubleClickEvent(QMouseEvent *event) { m_maximizeButton->click(); } void TitleBar::mousePressEvent(QMouseEvent *event) { // 鼠标左键按下事件 if (event->button() == Qt::LeftButton) { // 记录鼠标左键状态 m_leftButtonPressed = true; //记录鼠标在屏幕中的位置 m_start = event->globalPos(); } } void TitleBar::mouseMoveEvent(QMouseEvent *event) { // 持续按住才做对应事件 if(m_leftButtonPressed) { //将父窗体移动到父窗体原来的位置加上鼠标移动的位置:event->globalPos()-m_start parentWidget()->move(parentWidget()->geometry().topLeft() + event->globalPos() - m_start); //将鼠标在屏幕中的位置替换为新的位置 m_start = event->globalPos(); } } void TitleBar::mouseReleaseEvent(QMouseEvent *event) { // 鼠标左键释放 if (event->button() == Qt::LeftButton) { // 记录鼠标状态 m_leftButtonPressed = false; } } bool TitleBar::eventFilter(QObject *obj, QEvent *event) { switch(event->type()) { //设置标题 case QEvent::WindowTitleChange: { QWidget *pWidget = qobject_cast<QWidget *>(obj); if (pWidget) { m_titleLabel->setText(pWidget->windowTitle()); return true; } } //设置图标 case QEvent::WindowIconChange: { QWidget *pWidget = qobject_cast<QWidget *>(obj); if (pWidget) { QIcon icon = pWidget->windowIcon(); m_iconLabel->setPixmap(icon.pixmap(m_iconLabel->size())); return true; } } // 窗口状态变化、窗口大小变化 case QEvent::WindowStateChange: case QEvent::Resize: updateMaximize(); return true; } return QWidget::eventFilter(obj, event); } void TitleBar::updateMaximize() { QWidget *pWindow = this->window(); if (pWindow->isTopLevel()) { bool bMaximize = pWindow->isMaximized(); if (bMaximize) { m_maximizeButton->setToolTip(tr("Restore")); m_maximizeButton->setProperty("maximizeProperty", "restore"); } else { m_maximizeButton->setProperty("maximizeProperty", "maximize"); m_maximizeButton->setToolTip(tr("Maximize")); } m_maximizeButton->setStyle(QApplication::style()); } } void TitleBar::onClicked() { QPushButton *pButton = qobject_cast<QPushButton *>(sender()); QWidget *pWindow = this->window(); if (pWindow->isTopLevel()) { if (pButton == m_minimizeButton) { pWindow->showMinimized(); } else if (pButton == m_maximizeButton) { pWindow->isMaximized() ? pWindow->showNormal() : pWindow->showMaximized(); } else if (pButton == m_closeButton) { pWindow->close(); } } }
QWindowBase.h文件:
#ifndef QWINDOWBASE_H #define QWINDOWBASE_H #include <QFrame> #include <QWidget> #include <QVBoxLayout> #include "TitleBar.h" /** * @brief 界面组件基类 * @note QWindowBase界面组件主要用作顶层窗口,对于非顶层窗口的界面组件使用QWidget。 */ class QWindowBase : public QFrame { Q_OBJECT public: QWindowBase(QFrame* parent = NULL); /** * @brief 设置标题 * @param title,输入参数,标题内容 */ void setWindowTitle(const QString& title); /** * @brief 设置标题栏的图标 * @param iconPath,输入参数,图标资源路径 */ void SetTitleBarIcon(const QString& iconPath); /** * @brief 获取内容组件对象指针 * @return 返回QWidget* */ QWidget* contentWidget(); /** * @brief 设置标题栏高度 * @param h,输入参数,标题栏高度 */ void setWindowTitleHeight(int h); private: QWidget* m_contentWidget;//内容组件 TitleBar* m_titleBar;//标题栏 QVBoxLayout* m_layout;//布局管理器 }; #endif // QWINDOWBASE_H
QWindowBase.cpp文件:
#include "QWindowBase.h" QWindowBase::QWindowBase(QFrame *parent): QFrame(parent) { setWindowFlags(windowFlags() | Qt::FramelessWindowHint); m_titleBar = new TitleBar(this); m_contentWidget = new QWidget(this); m_contentWidget->setObjectName("Contents"); m_layout = new QVBoxLayout; m_layout->addWidget(m_titleBar); m_layout->addWidget(m_contentWidget); m_layout->setSpacing(0); m_layout->setContentsMargins(0, 0, 0, 0); setLayout(m_layout); } void QWindowBase::setWindowTitle(const QString &title) { m_titleBar->setWindowTitle(title); } void QWindowBase::SetTitleBarIcon(const QString &iconPath) { m_titleBar->SetTitleBarIcon(iconPath); } QWidget *QWindowBase::contentWidget() { return m_contentWidget; } void QWindowBase::setWindowTitleHeight(int h) { m_titleBar->setFixedHeight(h); }
CommonHelper.h文件:
#ifndef COMMONHELPER_H #define COMMONHELPER_H #include <QString> #include <QFile> #include <QApplication> #include <QDebug> #include <QColor> #include <QPalette> /** * @brief 通用功能辅助类 */ class CommonHelper { public: /** * @brief 为应用程序设置QSS样式表 * @param filepath,输入参数,QSS文件路径 */ static void setStyleSheet(const QString& filepath) { //加载样式文件 QFile qss(filepath); if(qss.open(QFile::ReadOnly)) { QString stylesheet = QLatin1String(qss.readAll()); QString paletteColor = stylesheet.mid(20, 7); qApp->setPalette(QPalette(QColor(paletteColor))); qApp->setStyleSheet(stylesheet); } } }; #endif // COMMONHELPER_H
main.cpp文件:
#include <QApplication> #include "CommonHelper.h" #include "QWindowBase.h" #include <QPushButton> #include <QVBoxLayout> #include <QHBoxLayout> #include <QTreeView> int main(int argc, char *argv[]) { QApplication a(argc, argv); QWindowBase w; w.setWindowTitle("WidgetBase"); QPushButton* button1 = new QPushButton("OK"); QHBoxLayout* hLayout1 = new QHBoxLayout; hLayout1->addStretch(1); hLayout1->addWidget(button1); QVBoxLayout* layout = new QVBoxLayout; QTreeView* treeView = new QTreeView; layout->addWidget(treeView); layout->addLayout(hLayout1); layout->addStretch(1); w.contentWidget()->setLayout(layout); w.setWindowTitleHeight(40); w.show(); CommonHelper::setStyleSheet("://qss/lightblue.qss"); return a.exec(); }
工程文件:
QT += core gui greaterThan(QT_MAJOR_VERSION, 4): QT += widgets TARGET = TitleBarDemo TEMPLATE = app # The following define makes your compiler emit warnings if you use # any feature of Qt which has been marked as deprecated (the exact warnings # depend on your compiler). Please consult the documentation of the # deprecated API in order to know how to port your code away from it. DEFINES += QT_DEPRECATED_WARNINGS # You can also make your code fail to compile if you use deprecated APIs. # In order to do so, uncomment the following line. # You can also select to disable deprecated APIs only up to a certain version of Qt. #DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0 SOURCES += \ main.cpp \ TitleBar.cpp \ QWindowBase.cpp HEADERS += \ TitleBar.h \ CommonHelper.h \ QWindowBase.h RESOURCES += \ TitileBarDemo.qrc
工程目录结构:
3、自定义窗体基类结果展示
运行结果:
-
QT自定义标题栏
2021-07-30 14:24:391、自定义标题栏 2、QT自带标题栏 自定义标题栏类的代码 1、ui界面 2、.h #include <QWidget> #include <QEvent> #include <QDockWidget> #include <QMouseEvent> namespace Ui { class...效果
1、自定义标题栏
2、QT自带标题栏
自定义标题栏类的代码
1、ui界面
2、.h#include <QWidget> #include <QEvent> #include <QDockWidget> #include <QMouseEvent> namespace Ui { class mTitleBar; } class mTitleBar : public QWidget { //Q_OBJECT public: explicit mTitleBar(QString title,QWidget *parent = nullptr); ~mTitleBar(); void mousePressEvent(QMouseEvent *event); void mouseMoveEvent(QMouseEvent *event); void mouseReleaseEvent(QMouseEvent *event); private: Ui::mTitleBar *ui; bool mPressBool; QPoint mouseStartPoint; QPoint mwindowTopLeftPoint; QDockWidget* mpDockMouse; };
3、.cpp
#include "mtitlebar.h" #include "ui_mtitlebar.h" #include <QDockWidget> #include <QWidget> //构造函数 mTitleBar::mTitleBar(QString title,QWidget *parent) : QWidget(parent), ui(new Ui::mTitleBar) { ui->setupUi(this); mpDockMouse = new QDockWidget(this); mpDockMouse->hide(); ui->label->setText(title); //囗:最大化/恢复 connect(ui->pushButton, &QPushButton::clicked, [=] { mpDockMouse = qobject_cast<QDockWidget*>(parentWidget()); if (mpDockMouse != nullptr) { if(mpDockMouse->isMaximized()) //显示原来的大小 { mpDockMouse->showNormal(); } else //最大化 { mpDockMouse->showMaximized(); } } }); //× 关闭 connect(ui->pushButton2, &QPushButton::clicked, [=] { mpDockMouse = qobject_cast<QDockWidget*>(parentWidget()); if (mpDockMouse != nullptr) { mpDockMouse->close(); } }); //- 最小化 connect(ui->pushButton3, &QPushButton::clicked, [=] { mpDockMouse = qobject_cast<QDockWidget*>(parentWidget()); // mpDockMouse->showMinimized(); mpDockMouse->hide(); }); }
//鼠标事件 void mTitleBar::mousePressEvent(QMouseEvent *event) { if(event->button() == Qt::LeftButton) { mPressBool = true; //获得鼠标的初始位置 mouseStartPoint = event->globalPos(); //获得窗口的初始位置 mpDockMouse = qobject_cast<QDockWidget*>(parentWidget()); mwindowTopLeftPoint = mpDockMouse->frameGeometry().topLeft(); } } void mTitleBar::mouseMoveEvent(QMouseEvent *event) { if(mPressBool) { //获得鼠标移动的距离 QPoint distance = event->globalPos() - mouseStartPoint; //改变窗口的位置 mpDockMouse = qobject_cast<QDockWidget*>(parentWidget()); mpDockMouse->move(mwindowTopLeftPoint + distance); } } void mTitleBar::mouseReleaseEvent(QMouseEvent *event) { if(event->button() == Qt::LeftButton) { mPressBool = false; } }
类设置自定义标题栏
this->setTitleBarWidget(new mTitleBar("Cap",this));
百度网盘链接
提取码:wzds
自定义标题栏 -
myWidget_qt自定义标题栏_qt自定义标题_mywidget_
2021-09-30 04:37:06qt自定义标题栏,可任意改变标题栏的各种颜色大小字体位置等样式 -
Qt 自定义标题栏
2019-01-23 15:52:17QWidget及其子类窗体组件的标题栏受操作系统的控制,即标题栏的界面风格与操作系统的主题风格相同,工程实践中需要开发者自行定义,达到美化应用程序界面的目的。开发环境是Qt5.7,调试成功,可自行下载,如有问题请... -
Qt笔记(四十五)之Qt自定义标题栏
2022-04-08 13:59:07Qt自定义标题栏 -
实现qt自定义标题栏的鼠标点击拖动
2022-05-16 09:45:15 -
Qt5.9自定义标题栏源代码
2018-07-19 18:54:17本源代码是用Qt5.9的Creator编译和构建,主要功能是实现自定义标题栏,而屏蔽系统自带的标题栏。具体的讲解和用法可以参考我的博客:https://blog.csdn.net/naibozhuan3744/article/details/81120544 -
Qt 实现 自定义窗口标题栏
2016-12-07 17:06:46以上代码用Qt实现了自定义窗口标题栏,非常实用,提供了窗口图标、窗口标题、最小化、最大化、关闭按钮等几个部分。可以应用到每一个窗口中去,保持每个窗口外观的一致性,同时自定义的标题栏也比系统自带的漂亮很多... -
QT自定义标题栏窗口移动
2021-07-30 11:05:28设置自定义的标题栏需要修改鼠标移动事件,这样窗口才能移动。哪个窗口不能移动,就再这个窗口的类中添加下列代码。 有一点点的bug,窗口会突然移动,后续修改。 代码 .h文件 void mousePressEvent(QMouseEvent *... -
Qt自定义标题栏用法
2019-09-27 14:38:38其中,自定义标题栏主要原理是,屏蔽原来的标题栏,然后用QVBoxLayout垂直布局管理器,加载一个标题栏QWidget。其中,这个标题栏QWidget里面自定义标题栏的功能按钮,比如图标、图标内容、最大化按钮(QWidget::... -
Qt自定义标题栏源码V1.0
2022-04-08 14:27:32自定义标题栏源码,实现了 1.鼠标左键点击移动 2.最小化 最大化/恢复 关闭程序功能 3.双击鼠标最大化/恢复功能 ************************************************************************************************... -
Qt自定义标题栏(可移动,可伸缩)
2021-12-08 19:06:49我之前写了自定义标题栏已经实现可移动,可伸缩窗口了,但是往窗口里面添加控件在窗口边缘时重叠时没有改变光标,导致不能伸缩窗口,现在我终于解决了这个问题! gitee地址:... -
Qt自定义标题栏-移动窗口
2021-10-11 00:29:29众所周知,一个最简单的窗口也是有标题栏的 Widnows默认提供的标题栏上有: 图标-窗口标题-Min-Max-Close按钮 但是,这未免太过局限 高自由度的自定义是极客(Geek)精神不可或缺的一部分 如果你想在标题栏上增加/... -
关于Qt自定义标题栏
2021-08-07 00:15:33这种就是需要自定义标题栏。 最近项目用到了自定义标题栏 自定义标题栏分为几个步骤: 1.隐藏QT自身的标题栏 2.用一个QWidget充当标题栏,在QWidget里面放置你想要的功能控件 3.在QWidget的基础上加入最基本的控件:... -
Qt自定义标题栏无边框窗口
2021-12-13 16:52:57参考链接: 搬运官方参考例子 ...Qt 使用windows api实现自定义标题栏无边框窗口,给出了去边框导致的最大化后像素偏移的解决方案 VC++实现阴影窗口,通过创建子窗口来实现阴影,设置跟随父窗口,有参考价值 ... -
Qt 自定义标题栏的拖拽
2020-10-12 15:25:07.h protected: //标题栏的拖拽 void mousePressEvent(QMouseEvent *event); void mouseMoveEvent(QMouseEvent *event);...//标题栏的拖拽,鼠标不在标题栏范围内无效 void mousePressEvent(QMouseEvent *event) { -
qt自定义标题栏文本编辑器
2018-06-06 11:36:20qt自定义窗口标题栏,能移动和缩放,简易文本编辑器,可以把文本信息存储在图片中 。 -
Qt高级——Qt自定义标题栏
2020-11-20 16:27:21一、Qt自定义标题栏简介 QWidget及其子类窗体组件的标题栏受操作系统的控制,即标题栏的界面风格与操作系统的主题风格相同,工程实践中需要开发者自行定义,达到美化应用程序界面的目的。 二、Qt自定义标题栏实现 ... -
qt 自定义标题栏状态栏
2020-06-28 23:52:39// 隐藏标题栏 setWindowFlags(Qt::FramelessWindowHint); 头文件 void mousePressEvent(QMouseEvent *event); void mouseMoveEvent(QMouseEvent *event); void mouseReleaseEvent(QMouseEvent *event); //头... -
Qt自定义标题栏并实现拖拽
2017-09-25 22:54:54Qt自定义标题栏并实现拖拽 很多时候,Qt自带的窗体边框不能满足我们的需求,或者我们觉得由于系统的主题影响导致界面太丑了,我们需要自行定义一个好看并和普通标题栏功能相同的控件去替代,以达到美化我们的程序... -
QT自定义窗口 自由拖动 自定义标题
2016-06-19 16:41:49QT自定义窗口 自由拖动 自定义标题