热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

QT快速开发自定义标题栏

前言大家在用QT进行客户端开发的时候,难免都会觉得原生的QT窗口标题栏很丑,希望能自绘漂亮的标题栏,实现方法其实也比较简单,

前言

大家在用QT进行客户端开发的时候,难免都会觉得原生的QT窗口标题栏很丑,希望能自绘漂亮的标题栏,实现方法其实也比较简单,网上资料也挺多,方法基本都差不多,不过我觉得不够简洁,对此我特地封装总结了一个最高效快捷的方法,3分钟实现一个自绘制标题栏,包含:左上角图标、标题、按钮、双击标题栏、最大化时候拖拽缩小、菜单栏等功能。


效果


方法

1、目标窗口添加标题栏、最大化最小化关闭按钮(该步最好每次使用时,从模板程序中直接复制)

2、窗口基类从QDialog改为QFramelessDialog,如果是QWidget的话,请参考QFramelessDialog自行编写QFramelessWidget即可,非常简单,只需要将QDialog改成QWidget即可,至于为什么我写程序更喜欢用QDialog而不是QWidget,主要原因是QDialog默认自带外边框,设置外边框更简单,而QWidget设置外边框比较麻烦,必须在ui中将边框宽度pad预留出来。

3、窗口构造函数中,调用无边框窗体初始化函数,头文件中已经写好几个宏函数直接调用即可,使用宏的情况下,必须保证标题栏、按钮对象名称一致,注意调用初始化函数一定要在ui.setupUi(this);后面。

核心初始化函数

void Init(QWidget *widget_title, //标题栏对象QPushButton *menuButton_Close,//关闭按钮 QPushButton *menuButton_Max, //最大化按钮QPushButton *menuButton_Min, //最小化按钮bool bResize, //窗体支持resizebool bMinHide, //点击close按钮时隐藏窗口,通常用在主窗口中bool bConnectClose); //当bMinHide为true时,是否自动处理隐藏

宏解释:

FRAMELESS_DIALOG_INIT    模态对话框(只有关闭按钮)

FRAMELESS_MAIN_DIALOG_INIT   常用主窗口(包含最大化 、最小化、关闭按钮、可resize)

关于Demo中qss样式、编辑可参考作者早期博文《QT-智能QSS设计器》

https://blog.csdn.net/redchairman/article/details/82012984


代码

#ifndef QFRAMELESSDIALOG_H
#define QFRAMELESSDIALOG_H#include class QFramelessDialog : public QDialog
{Q_OBJECTpublic:QFramelessDialog(QWidget *parent);~QFramelessDialog();void Init(QWidget *widget_title, QPushButton *menuButton_Close, QPushButton *menuButton_Max,QPushButton *menuButton_Min,bool bResize,bool bMinClose,bool bConnectClose);void setResizeable(bool resizeable);virtual void CloseDialog();
private:bool m_bMaximized;bool m_bMoveable;QPoint dragPosition;QRect m_rcNormal;protected:void mouseMoveEvent(QMouseEvent *e);void mousePressEvent(QMouseEvent *e);void mouseReleaseEvent(QMouseEvent *);void mouseDoubleClickEvent(QMouseEvent *event);bool nativeEvent(const QByteArray & eventType, void * message, long * result);void paintEvent(QPaintEvent *event);void keyPressEvent(QKeyEvent* e);public slots:
/* void sltCloseClick();*/void sltClickMin();void sltClickMaxRestore();void sltCloseDialog();public:bool m_bResize;QPushButton *m_menuButton_Close;QPushButton *m_menuButton_Max;QPushButton *m_menuButton_Min;QWidget *m_widget_title;bool m_bMinClose;bool m_bConnectClose;
};#define FRAMELESS_DIALOG_INIT() Init(ui.widget_title, ui.menuButton_Close, nullptr, nullptr, false, false, true)
#define FRAMELESS_MAIN_DIALOG_INIT() Init(ui.widget_title, ui.menuButton_Close, ui.menuButton_Max, ui.menuButton_Min, true, true, true)
#define FRAMELESS_MAIN_DIALOG_NOCLOSE_INIT() Init(ui.widget_title, ui.menuButton_Close, ui.menuButton_Max, ui.menuButton_Min, true, true, false)#define FRAMELESS_DIALOG_INIT2() Init(ui->widget_title, ui->menuButton_Close, nullptr, nullptr, false, false, true)
#define FRAMELESS_MAIN_DIALOG_INIT2() Init(ui->widget_title, ui->menuButton_Close, ui->menuButton_Max, ui->menuButton_Min, true, true, true)
#define FRAMELESS_MAIN_DIALOG_NOCLOSE_INIT2() Init(ui->widget_title, ui->menuButton_Close, ui->menuButton_Max, ui->menuButton_Min, true, true, false)#endif // QFRAMELESSDIALOG_H

 

#include "stdafx.h"
#include "QFramelessDialog.h"
#include "QIconHelper.hpp"QFramelessDialog::QFramelessDialog(QWidget *parent): QDialog(parent), m_bMaximized(false), m_bMoveable(false), m_bResize(false), m_menuButton_Close(nullptr), m_menuButton_Max(nullptr), m_menuButton_Min(nullptr), m_widget_title(nullptr), m_bMinClose(false)
{
/* setAttribute(Qt::WA_TranslucentBackground);*/setWindowFlags(Qt::FramelessWindowHint | Qt::Dialog | Qt::WindowMinMaxButtonsHint);setWindowModality(Qt::WindowModal);setFocusPolicy(Qt::ClickFocus);
}QFramelessDialog::~QFramelessDialog()
{}void QFramelessDialog::Init(QWidget *widget_title, QPushButton *menuButton_Close, QPushButton *menuButton_Max,QPushButton *menuButton_Min,bool bResize,bool bMinClose,bool bConnectClose)
{m_bResize = bResize;m_bMinClose = bMinClose;m_bConnectClose = bConnectClose;m_menuButton_Min = menuButton_Min;m_menuButton_Max = menuButton_Max;m_menuButton_Close = menuButton_Close;m_widget_title = widget_title;if (m_menuButton_Close){m_menuButton_Close->setFocusPolicy(Qt::ClickFocus);QIconHelper::SetIcon(m_menuButton_Close, QChar(0xf00d), 12);if (m_bMinClose){if (m_bConnectClose){connect(m_menuButton_Close, SIGNAL(clicked()), this, SLOT(hide()));}}else{connect(m_menuButton_Close, SIGNAL(clicked()), this, SLOT(sltCloseDialog()));}}if (m_menuButton_Max){m_menuButton_Max->setFocusPolicy(Qt::ClickFocus);QIconHelper::SetIcon(m_menuButton_Max, QChar(0xf096), 12);connect(m_menuButton_Max, SIGNAL(clicked()), this, SLOT(sltClickMaxRestore()));}if (m_menuButton_Min){m_menuButton_Min->setFocusPolicy(Qt::ClickFocus);QIconHelper::SetIcon(m_menuButton_Min, QChar(0xf068), 12);connect(m_menuButton_Min, SIGNAL(clicked()), this, SLOT(sltClickMin()));}return;
}void QFramelessDialog::CloseDialog()
{close();
}void QFramelessDialog::sltCloseDialog()
{CloseDialog();
}void QFramelessDialog::mousePressEvent(QMouseEvent *event)
{if (isFullScreen()){return;}if (event->button() == Qt::LeftButton && m_widget_title){dragPosition = event->globalPos() - frameGeometry().topLeft();QRect rect = m_widget_title->rect();if (rect.contains(event->pos())){m_bMoveable = true;}}event->accept();
}void QFramelessDialog::mouseMoveEvent(QMouseEvent *event)
{if (isFullScreen()){return;}if (event->buttons() & Qt::LeftButton && m_bMoveable){if (isMaximized()){int nWidth = m_rcNormal.width();int nHeight = m_rcNormal.height();float fx = (float)event->pos().x() / (float)rect().width();//屏幕大小int old_x = m_rcNormal.width() * fx + m_rcNormal.left();int old_y = m_rcNormal.top() + event->pos().y();QPoint pt_new(m_rcNormal.left() + event->globalPos().x() - old_x, m_rcNormal.top() + event->globalPos().y() - old_y);m_rcNormal.moveTopLeft(pt_new);sltClickMaxRestore();//m_rcNormaldragPosition = event->globalPos() - frameGeometry().topLeft();}else{move(event->globalPos() - dragPosition);}}event->accept();}void QFramelessDialog::mouseReleaseEvent(QMouseEvent *event)
{if (isFullScreen()){return;}if (m_bMoveable){m_bMoveable = false;}event->accept();
}void QFramelessDialog::mouseDoubleClickEvent(QMouseEvent *event)
{if (m_bResize == false){return;}if (m_menuButton_Max == nullptr || m_menuButton_Min == nullptr){return;}if (isFullScreen()){return;}if (event->buttons() & Qt::LeftButton && m_widget_title){QRect rect = m_widget_title->rect();if (rect.contains(event->pos())){sltClickMaxRestore();}}event->accept();
}void QFramelessDialog::sltClickMin()
{showMinimized();
}void QFramelessDialog::sltClickMaxRestore()
{if (isMaximized()){showNormal();setGeometry(m_rcNormal);qDebug() <setToolTip(QStringLiteral("最大化"));}else{m_rcNormal &#61; geometry();showMaximized();QIconHelper::SetIcon(m_menuButton_Max, QChar(0xf079), 10);m_menuButton_Max->setToolTip(QStringLiteral("还原"));}
}bool QFramelessDialog::nativeEvent(const QByteArray & eventType, void * message, long * result)
{Q_UNUSED(eventType);const int HIT_BORDER &#61; 4;const MSG *msg &#61; static_cast(message);if (msg->message &#61;&#61; WM_NCCALCSIZE){*result &#61; 0;return true;}else if (msg->message &#61;&#61; WM_NCHITTEST){if (m_bResize &#61;&#61; false || m_widget_title &#61;&#61; nullptr){return QDialog::nativeEvent(eventType, message, result);}if (isMaximized()){return false;}int xPos &#61; ((int)(short)LOWORD(msg->lParam)) - this->frameGeometry().x();int yPos &#61; ((int)(short)HIWORD(msg->lParam)) - this->frameGeometry().y();if (xPos >&#61; 0 && xPos &#61; 0 && yPos (this->width() - HIT_BORDER) && xPos <(this->width() - 0) && yPos > 0 && yPos 0 && xPos (this->height() - HIT_BORDER) && yPos <(this->height() - 0)) {*result &#61; HTBOTTOMLEFT;return true;}if (xPos >(this->width() - HIT_BORDER) && xPos <(this->width() - 0) && yPos >(this->height() - HIT_BORDER) && yPos <(this->height() - 0)) {*result &#61; HTBOTTOMRIGHT;return true;}if (xPos >&#61; 0 && xPos (this->width() - HIT_BORDER) && xPos <(this->width() - 0)) {*result &#61; HTRIGHT;return true;}if (yPos >&#61; 0 && yPos (this->height() - HIT_BORDER) && yPos <(this->height() - 0)) {*result &#61; HTBOTTOM;return true;}if (m_widget_title->geometry().contains(QPoint(xPos, yPos))){*result &#61; HTCAPTION;return false;}return false;}return false;
}#define SHADOW_BORDER 6
void QFramelessDialog::paintEvent(QPaintEvent *event)
{return QDialog::paintEvent(event);
//
// QPainterPath path;
// path.setFillRule(Qt::WindingFill);
// path.addRect(SHADOW_BORDER, SHADOW_BORDER, this->width()-2*SHADOW_BORDER, this->height()-2*SHADOW_BORDER);
//
// QPainter painter(this);
// painter.setRenderHint(QPainter::Antialiasing, true);
// painter.fillPath(path, QBrush(Qt::white));
//
// QColor color(0, 0, 0, 60);
// for(int i&#61;0; i// {
// QPainterPath path;
// path.setFillRule(Qt::WindingFill);
// path.addRect(SHADOW_BORDER-1-i, SHADOW_BORDER-1-i, this->width()-(SHADOW_BORDER-i)*2, this->height()-(SHADOW_BORDER-i)*2);
// color.setAlpha(40 - i * 7);
// painter.setPen(color);
// painter.drawPath(path);
// }
}void QFramelessDialog::keyPressEvent(QKeyEvent* e)
{qDebug()<key();switch (e->key()){case Qt::Key_Return:break;case Qt::Key_Enter:break;case Qt::Key_Escape:{if (m_bMinClose)break;}default:QDialog::keyPressEvent(e);}
}

调用示例&#xff1a;

#include
#include "ui_QSubDialog.h"
#include "QFramelessDialog.h"class QSubDialog : public QFramelessDialog
{Q_OBJECTpublic:QSubDialog(QWidget *parent &#61; 0);~QSubDialog();private:Ui::QSubDialog ui;
};

#include "stdafx.h"
#include "QSubDialog.h"QSubDialog::QSubDialog(QWidget *parent): QFramelessDialog(parent)
{ui.setupUi(this);FRAMELESS_DIALOG_INIT();
}QSubDialog::~QSubDialog()
{}

源代码下载

 


QT实战派交流群

群号码&#xff1a;1149411109

群名称&#xff1a;Qt实战派学习群

 

 


推荐阅读
  • vue使用
    关键词: ... [详细]
  • 向QTextEdit拖放文件的方法及实现步骤
    本文介绍了在使用QTextEdit时如何实现拖放文件的功能,包括相关的方法和实现步骤。通过重写dragEnterEvent和dropEvent函数,并结合QMimeData和QUrl等类,可以轻松实现向QTextEdit拖放文件的功能。详细的代码实现和说明可以参考本文提供的示例代码。 ... [详细]
  • Iamtryingtomakeaclassthatwillreadatextfileofnamesintoanarray,thenreturnthatarra ... [详细]
  • 本文主要解析了Open judge C16H问题中涉及到的Magical Balls的快速幂和逆元算法,并给出了问题的解析和解决方法。详细介绍了问题的背景和规则,并给出了相应的算法解析和实现步骤。通过本文的解析,读者可以更好地理解和解决Open judge C16H问题中的Magical Balls部分。 ... [详细]
  • 本文讨论了一个关于cuowu类的问题,作者在使用cuowu类时遇到了错误提示和使用AdjustmentListener的问题。文章提供了16个解决方案,并给出了两个可能导致错误的原因。 ... [详细]
  • 本文介绍了P1651题目的描述和要求,以及计算能搭建的塔的最大高度的方法。通过动态规划和状压技术,将问题转化为求解差值的问题,并定义了相应的状态。最终得出了计算最大高度的解法。 ... [详细]
  • 本文介绍了UVALive6575题目Odd and Even Zeroes的解法,使用了数位dp和找规律的方法。阶乘的定义和性质被介绍,并给出了一些例子。其中,部分阶乘的尾零个数为奇数,部分为偶数。 ... [详细]
  • Linux环境变量函数getenv、putenv、setenv和unsetenv详解
    本文详细解释了Linux中的环境变量函数getenv、putenv、setenv和unsetenv的用法和功能。通过使用这些函数,可以获取、设置和删除环境变量的值。同时给出了相应的函数原型、参数说明和返回值。通过示例代码演示了如何使用getenv函数获取环境变量的值,并打印出来。 ... [详细]
  • C++字符字符串处理及字符集编码方案
    本文介绍了C++中字符字符串处理的问题,并详细解释了字符集编码方案,包括UNICODE、Windows apps采用的UTF-16编码、ASCII、SBCS和DBCS编码方案。同时说明了ANSI C标准和Windows中的字符/字符串数据类型实现。文章还提到了在编译时需要定义UNICODE宏以支持unicode编码,否则将使用windows code page编译。最后,给出了相关的头文件和数据类型定义。 ... [详细]
  • EPICS Archiver Appliance存储waveform记录的尝试及资源需求分析
    本文介绍了EPICS Archiver Appliance存储waveform记录的尝试过程,并分析了其所需的资源容量。通过解决错误提示和调整内存大小,成功存储了波形数据。然后,讨论了储存环逐束团信号的意义,以及通过记录多圈的束团信号进行参数分析的可能性。波形数据的存储需求巨大,每天需要近250G,一年需要90T。然而,储存环逐束团信号具有重要意义,可以揭示出每个束团的纵向振荡频率和模式。 ... [详细]
  • 在Android开发中,使用Picasso库可以实现对网络图片的等比例缩放。本文介绍了使用Picasso库进行图片缩放的方法,并提供了具体的代码实现。通过获取图片的宽高,计算目标宽度和高度,并创建新图实现等比例缩放。 ... [详细]
  • IhaveconfiguredanactionforaremotenotificationwhenitarrivestomyiOsapp.Iwanttwodiff ... [详细]
  • android listview OnItemClickListener失效原因
    最近在做listview时发现OnItemClickListener失效的问题,经过查找发现是因为button的原因。不仅listitem中存在button会影响OnItemClickListener事件的失效,还会导致单击后listview每个item的背景改变,使得item中的所有有关焦点的事件都失效。本文给出了一个范例来说明这种情况,并提供了解决方法。 ... [详细]
  • 本文介绍了九度OnlineJudge中的1002题目“Grading”的解决方法。该题目要求设计一个公平的评分过程,将每个考题分配给3个独立的专家,如果他们的评分不一致,则需要请一位裁判做出最终决定。文章详细描述了评分规则,并给出了解决该问题的程序。 ... [详细]
  • 本文介绍了一个题目的解法,通过二分答案来解决问题,但困难在于如何进行检查。文章提供了一种逃逸方式,通过移动最慢的宿管来锁门时跑到更居中的位置,从而使所有合格的寝室都居中。文章还提到可以分开判断两边的情况,并使用前缀和的方式来求出在任意时刻能够到达宿管即将锁门的寝室的人数。最后,文章提到可以改成O(n)的直接枚举来解决问题。 ... [详细]
author-avatar
爱吹泡泡de鱼_436
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有