范文健康探索娱乐情感热点
投稿投诉
热点动态
科技财经
情感日志
励志美文
娱乐时尚
游戏搞笑
探索旅游
历史星座
健康养生
美丽育儿
范文作文
教案论文

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(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  #include  #include  #include  #include  #include  #include  #include  #include  #include  /** * @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(obj); if (pWidget) { m_titleLabel->setText(pWidget->windowTitle()); return true; } } //设置图标 case QEvent::WindowIconChange: { QWidget *pWidget = qobject_cast(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(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  #include  #include  #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  #include  #include  #include  #include  #include  /** * @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
  点击领取Qt学习资料+视频教程~「链接」
  main.cpp文件:#include  #include "CommonHelper.h" #include "QWindowBase.h" #include  #include  #include  #include  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、自定义窗体基类结果展示
  运行结果:

同样工龄,早晚差一年退休,养老金为什么晚退休低?在正常情况下,应该是退的越晚,缴纳养老金时间越长,退休后养老金拿的越高。假如出现同样工龄,早晚差一年退休,养老金出现低的情况,这就说明晚退的人,在缴纳养老保险金的基数上,要比早退的上海宝钢集团正式职工退休后,一个月能超过9000退休金吗?宝钢集团成立后,吃掉了上钢五厂,上钢一厂,上海钢管厂,这些在分厂的退休人员所拿的养老金不高的,因为这些分厂的职工大都下岗,或者内部退休了。首先楼主的提问比较笼统,其次现在已经没有宝如果死刑犯在行刑的前一天突发重病,第二天还用执行死刑吗?如果死刑犯在临刑前一天突发重病,还会被执行死刑吗?一个真实的故事告诉你,突发重病之后,该给予的医疗治疗肯定会给予,但同时,该执行的死刑依旧会执行。老张是红丝带死刑犯,红丝带意味着什住在顶楼,水压不够,用不了热水器,怎么办?家里的水压不够确实很糟心,这种问题一般都是出现在高层的老楼房中,其它的地方虽然也有但是出现的几率不大,这也是个人一直不喜欢高层顶楼的原因之一。那么住在顶楼,水压不够用不了热水器怎么同样结交黑道,张无忌甚至当了头子,为什么很多人批评令狐冲,却没人批评张无忌?简单说,你看的时候,是站在了主角视角才觉得奇怪。如果换成书里普通武林人士的视角,再想想看就不奇怪了。首先,令狐冲的独孤九剑和吸星大法,江湖上的大多数人,都不知道令狐冲有这两门无关,为什么别人一眼就看出,你是老实人?哪几点暴露的?1眼神直勾勾。2说话实在,有什么,说什么。3不会说场面话,不会见风使舵。4反应慢,接话慢,理解不了别人说话的含义。5听话,让干什么就干什么。6别人欺负,不会反击,不停退让。7遇到机国企稳定的收入会不会使你觉得没有未来?国企稳定的收入不但不会让我觉得没有未来,反而让我觉得很满意。因为现在疫情迟迟难以结速,市场震荡,什么都不好干,民营企业一样困难,个体小买卖更难做。国有企业船大好掉头,船大抗风浪。在事业副高职称,参公后转为一级主任科员划算吗?怎么会有这种好事?首先,事业副高职称人员在参公后以科员对待,不可能直接转为一级主任科员。其次,参展公务员的一级主任科员在待遇上与副高职称人员有一定区别。老马在林业局下属事业单位,2上世纪九十年左右,那批买非农业户口的人,你现在后悔了吗?当年由农业户口,花了5000大洋买成了非农业户口,现在真是悔青了肠子。那时买非农业户口的目的,是想吃上商品粮,烧上供应煤,参加招工当个工人,想得美美哒。没想到刚买完不久,以前早就吃我贵阳本地人,后悔当年没买花果园买的未来方舟,现置换来得及吗?花果园和未来方舟,2个楼盘都是贵阳近20年来兴起的大型楼盘,而且都是由本土房地产开发商打造,很多都是贵州省内的人买,未来方舟体量上没有花果园大,花果园占地达6000多亩,总建筑面积企业改制,职工档案移交社保局,办理退休须要其他证明,请问不合格档案你是如何交收的?企业改制,职工档案移交社保局,办理退休需要其他证明,请问不合格档案是如何交收的?你说的这种情况的确存在,很多企业改制以后,从原来的国有企业变成了股份制企业或是民营企业,失去了职工档
张作霖遗言万万不可让此人来东北,多年后他才明白父亲的英明1928年6月4日,张作霖被炸的遍体鳞伤,临终之际,他嘱咐副官,一定要告诉自己的儿子张学良,万万不可让一人去东北。张学良似懂非懂,直到多年后,他才明白,父亲的英明。这个人,就是张作容易出汗的人,一般是什么体质?这3种体质蛮多见体质不同身体健康状况不一样,有的人动不动就出汗,就连在秋冬季节也容易冒冷汗,也有的人一年四季基本上出汗量很少,有时出去户外活动有一定的运动量依然不出汗,这其中的差别是什么应该去详细起床就叠被?用水冲洗肉?别让这8种好习惯,损害家人健康!俗话说细节决定成败。身体是否健康同样取决于生活小细节,做好饮食运动和作息等多方面护理,那么身体健康又长寿。现代人越来越注重于自身健康,摒弃不良的行为习惯。然而,有些习惯并没有人们想肺部最爱这3种食物,每天吃一种,润肺去燥,止咳化痰,健康过年许多人好不容易从阳性感染的高烧中坚持过来,准备拥抱阳康的身体时,一声声的咳嗽却让人苦不堪言。久咳不愈,除了对症用药外,我们也需要润肺,清肺。阳伤肺,阳过第一时间就需要先养肺,最直接收好这三款春季养肝护脾祛湿养生汤广东地区春季短,大约只有从立春至清明这段时间,总体偏温偏湿,养生大原则以养肝顺肝养脾为主,注意此时温燥邪气多。春属木,与肝相应,味属酸,在整个春季里,食养原则是减酸益甘而养脾气。因约翰斯托克顿NBA历史助攻抢断王,平凡的身躯铸就不凡的伟大!世人都知道乔丹的10次得分王,以及连续7次的得分王的伟大。而那个男人的连续9次助攻王,同样是后人难以企及的高度!他可以说是真正把控球后卫发挥到极致的男人,他是完美的团队球员,但也是迈尔斯追梦的领导力是球队成功原因他可以帮你以最高水平赢直播吧1月20日讯今日NBA常规赛,勇士将在客场挑战凯尔特人。追梦格林在赛前的播客节目中为本赛季球队的失利揽责,他表示自己没能成为一个真正的领袖。对此,勇士总经理迈尔斯在参加Ste曼联旧将滕哈赫用肖不用马奎尔,他在表明自己用人的立场直播吧1月20日讯前曼联后卫西尔维斯特表示,滕哈赫近期让卢克肖而不是马奎尔或者林德洛夫踢中卫,是在表明自己的用人立场。西尔维斯特说这实际上是滕哈赫在发表自己用人的立场,在中卫位置上53!斯诺克四强决出两席泰国黑马再爆冷门,连赢三位世界冠军2023年1月20日,斯诺克世界大奖赛继续进行,四强已出其二,泰国黑马诺庞。桑坎姆53淘汰马克。威廉姆斯,连赢塞尔比奥沙利文马克。威廉姆斯三位世界冠军,确实令人意想不到,马克。艾伦大爆冷!女单第二夺冠热门轰然出局,两根油条的比分有些辣眼聚焦澳网赛事,关注大牌表现。2023澳网结束第四个比赛日争夺,男女单打第二轮比赛陆续展开。女单赛场,罗德拉沃尔中心球场结束一场最后一场比赛。对阵的双方,分别是现世界排名第2并以2号印度赛八强诞生国羽9席,00后李诗沣力克李梓嘉,石宇奇屠龙未果北京时间1月19日,印度羽毛球公开赛(super750)继续展开18决赛的争夺,国羽共参与15场争夺,最终9胜6负。其中多场比赛面对强敌,结果也是喜忧参半。男单3人出战仅李诗沣21