记录下Qt的自定义标题栏。
提示:以下是本篇文章正文内容,下面案例可供参考
代码如下(示例):
#ifndef TITLEBAR_H
#define TITLEBAR_H
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include "windows.h"
#define PADDING 5
#ifndef SAFEDELETE
#define SAFEDELETE(pointer) \
{ \
if(pointer) \
{ \
delete pointer; \
} \
pointer = NULL; \
}
#endif
namespace TITLEBAR
{
enum WIDGETBYTTONTYPE
{
MAXWIDGET, //去掉最大化按钮
MINWIDGET, //去掉最小化按钮
CloseWIDGET, //去掉关闭按钮
ALLWIDGET, //去掉除关闭按钮外的所有按钮
NOBUTTON, //去除所有按钮
};
}
class TitleBar : public QFrame
{
Q_OBJECT
public:
explicit TitleBar(QWidget *parentWidget = nullptr);
enum Direction { UP = 0, LEFT, RIGHT, LEFTTOP, RIGHTTOP, NONE };
void initData();
void initBotton(); //初始化按钮
void initConnect(); //初始化值
void setWindowTitle(const QString &title); //设置标题
void setWindowIcon(const QString &icon); //设置图标(为空时隐藏图标)
void subWindowButton(const int &type); //设置按钮
void Shadow_Warning(); //设置阴影
void RemoveMaxMinButton(); //移除最大最小按钮
void Set_MaximizeFlag(); //设置双击标题栏是否可以最大、最小化
void Set_MouseShapeFlag(bool MouseShape); //设置标题栏是否可以改变大小
bool FileIsExist(QString strFile); //文件是否存在
void SetTitleLabelTextColor(int R,int G,int B); //修改标题显示文字颜色
const static int TITLEBARHEIGHT = 30; //标题栏高度
const static int CONTROLWIDTH = 30; //控件宽度
QRectF boundingRect() const;
QRectF leftBorder() const;
QRectF rightBorder() const;
QRectF topBorder() const;
QRectF bottomBorder() const;
void setMousePressCursorShape(const QPointF& pt, bool isShow = true);
public slots:
void showMax(); //最大化窗口
void showMin(); //最小化窗口
void showClose(); //关闭窗口
void set_ChildWindowColor(int R,int G,int B); //设置标题栏背景色
void ModifyTitleBarTip(); //修改标题栏按钮提示语言
signals:
void send_close(); //发送关闭信号
void send_showToolbar(); //发送显示/隐藏工具栏信号
private slots:
private:
QPushButton *maxButton; //最大化按钮
QPushButton *minButton; //最小化按钮
QPushButton *closeButton; //关闭按钮
QLabel *imgLabel; //图片框
QLabel *titleLabel; //标题名
QWidget *parentWidget; //父窗口
bool mousePress; //按钮点击标志位
QPoint movePoint; //鼠标移动需要记住的点
int switchFlag;
int MaximizeFlag; //双击是否最大化
int IsShow_Toolbar; //显示隐藏工具栏
int Original_window_x; //窗口x坐标
int Original_window_y; //窗口y坐标
int Original_window_Mywidth; //窗口宽度
int Original_window_Myheight; //窗口高度
bool isTitleBarResize; //标题栏是否可以改变大小
bool isLeftPressDown; //判断左键是否按下
Direction dir; //窗口大小改变时,记录改变方向
private:
void mousePressEvent(QMouseEvent * event); //鼠标点击事件
void mouseReleaseEvent(QMouseEvent *event); //鼠标释放事件
void mouseMoveEvent(QMouseEvent * event); //鼠标移动事件
void mouseDoubleClickEvent(QMouseEvent *event); //鼠标双击事件
bool eventFilter(QObject *obj, QEvent *event);
void paintEvent(QPaintEvent *event); //绘制事件
};
#endif // TITLEBAR_H
代码如下(示例):
#include "titlebar.h"
#include
/*************************** 构造函数 ***************************/
TitleBar::TitleBar(QWidget *parent) : QFrame(parent)
{
//设置父类窗口
parentWidget = parent;
//初始化参数
initData();
//初始化按钮
initBotton();
//初始化
initConnect();
//设置标题栏背景色
set_ChildWindowColor(70, 70, 70);
//设置标题栏显示文字颜色
SetTitleLabelTextColor(255, 255, 255);
//重置窗口大小
resize(parent->width(), TITLEBARHEIGHT);
setFixedHeight(TITLEBARHEIGHT);
//设置阴影
//Shadow_Warning();
}
void TitleBar::initData()
{
switchFlag = 1;
MaximizeFlag = 0;
isTitleBarResize = false;
IsShow_Toolbar = 1;
this->setMouseTracking(true);
this->setAttribute(Qt::WA_Hover, true);
this->installEventFilter(this);
isLeftPressDown = false;
this->dir = NONE;
}
void TitleBar::initBotton()
{
//最大化按钮设置图标
maxButton = new QPushButton(this);
maxButton->setFocusPolicy(Qt::NoFocus);
maxButton->setIcon(QPixmap("style/icons/max.png"));
//最小化按钮设置图标
minButton = new QPushButton(this);
minButton->setFocusPolicy(Qt::NoFocus);
minButton->setIcon(QPixmap("style/icons/min.png"));
//关闭按钮设置图标
closeButton = new QPushButton(this);
closeButton->setShortcut(tr("Ctrl+w"));
closeButton->setFocusPolicy(Qt::NoFocus);
closeButton->setIcon(QPixmap("style/icons/close.png"));
//设置标签
imgLabel = new QLabel(this);
titleLabel = new QLabel(this);
titleLabel->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
//设置控件大小
imgLabel->setFixedSize(CONTROLWIDTH - 5, CONTROLWIDTH - 5);
imgLabel->setScaledContents(true);
titleLabel->setMinimumSize(120, TITLEBARHEIGHT);
minButton->setFixedSize(CONTROLWIDTH, CONTROLWIDTH);
maxButton->setFixedSize(CONTROLWIDTH, CONTROLWIDTH);
closeButton->setFixedSize(CONTROLWIDTH, CONTROLWIDTH);
//设置控件图标大小
minButton->setIconSize(QSize(CONTROLWIDTH, CONTROLWIDTH));
maxButton->setIconSize(QSize(CONTROLWIDTH, CONTROLWIDTH));
closeButton->setIconSize(QSize(CONTROLWIDTH, CONTROLWIDTH));
//设置鼠标移至按钮上的提示信息
ModifyTitleBarTip();
//设置布局
QHBoxLayout *hBoxLayout = new QHBoxLayout;
hBoxLayout->addSpacing(5);
hBoxLayout->addWidget(imgLabel);
hBoxLayout->addSpacing(5);
hBoxLayout->addWidget(titleLabel);
hBoxLayout->addStretch();
hBoxLayout->addSpacing(5);
hBoxLayout->addWidget(minButton);
hBoxLayout->addWidget(maxButton);
hBoxLayout->addWidget(closeButton);
hBoxLayout->setSpacing(0);
hBoxLayout->setContentsMargins(0, 0, 2, 0);
this->setLayout(hBoxLayout);
}
/*************************** 设置标题 ***************************/
void TitleBar::setWindowTitle(const QString &title)
{
QFont myFont;
//设置文字大小
myFont.setPointSize(12);
//设置文字字体
myFont.setFamily(qApp->font().family());
titleLabel->setFont(myFont);
titleLabel->setText(title);
}
/*************************** 设置图标 ***************************/
void TitleBar::setWindowIcon(const QString &icon)
{
if (icon.isEmpty())
imgLabel->hide();
else
imgLabel->setPixmap(QPixmap(icon));
}
/*************************** 设置标题栏不需要显示的按钮 ***************************/
void TitleBar::subWindowButton(const int &type)
{
if(type == TITLEBAR::MINWIDGET)
{
SAFEDELETE(minButton);
}
else if(type == TITLEBAR::MAXWIDGET)
{
SAFEDELETE(maxButton);
}
else if(type == TITLEBAR::CloseWIDGET)
{
SAFEDELETE(closeButton);
}
else if(type == TITLEBAR::ALLWIDGET)
{
SAFEDELETE(minButton);
SAFEDELETE(maxButton);
}
else if (type == TITLEBAR::NOBUTTON)
{
SAFEDELETE(minButton);
SAFEDELETE(maxButton);
SAFEDELETE(closeButton);
}
}
void TitleBar::Shadow_Warning()
{
//窗口添加阴影效果
QGraphicsDropShadowEffect *shadow_effect = new QGraphicsDropShadowEffect;
shadow_effect->setOffset(0, 4);
shadow_effect->setColor(Qt::gray);
shadow_effect->setBlurRadius(6);
this->setGraphicsEffect(shadow_effect);
#if 0
//实现毛玻璃效果
QGraphicsBlurEffect* ef = new QGraphicsBlurEffect;
ef->setBlurRadius(1.5);
ef->setBlurHints(QGraphicsBlurEffect::AnimationHint);
this->setGraphicsEffect(ef);
#endif
}
//移除最大最小按钮
void TitleBar::RemoveMaxMinButton()
{
subWindowButton(TITLEBAR::ALLWIDGET);
}
//设置双击标题栏是否可以最大、最小化
void TitleBar::Set_MaximizeFlag()
{
MaximizeFlag = 1;
}
//文件是否存在
bool TitleBar::FileIsExist(QString strFile)
{
QFile tempFile(strFile);
return tempFile.exists();
}
//修改标题显示文字颜色
void TitleBar::SetTitleLabelTextColor(int R,int G,int B)
{
titleLabel->setStyleSheet(QString("QLabel{background-color:transparent;color:rgb(%1,%2,%3);outline: none;border:none;qproperty-alignment: 'AlignVCenter | AlignLeft';}").arg(R).arg(G).arg(B));
}
/*************************** 初始化 ***************************/
void TitleBar::initConnect()
{
//设置样式表
minButton->setStyleSheet("QPushButton{background-color:transparent;outline: none;border:none;}QPushButton:hover{padding-left:6px;padding-top:6px;}");
maxButton->setStyleSheet("QPushButton{background-color:transparent;outline: none;border:none;}QPushButton:hover{padding-left:6px;padding-top:6px;}");
closeButton->setStyleSheet("QPushButton{background-color:transparent;outline: none;border:none;border-radius: 0px;}QPushButton:hover{padding-left:6px;padding-top:6px;background-color:rgb(237,28,36);}");
//连接信号与槽
connect(minButton, SIGNAL(clicked(bool)), this, SLOT(showMin()));
connect(maxButton, SIGNAL(clicked(bool)), this, SLOT(showMax()));
connect(closeButton, SIGNAL(clicked(bool)), this, SLOT(showClose()));
}
/*************************** 最大化 ***************************/
void TitleBar::showMax()
{
if(parentWidget->geometry() == QApplication::desktop()->availableGeometry()) //判断是否是全屏
{
maxButton->setIcon(QPixmap("style/icons/max.png"));
//退出全屏时设置为原窗口的坐标位置和尺寸大小
parentWidget->setGeometry(Original_window_x, Original_window_y, Original_window_Mywidth, Original_window_Myheight);
}
else
{
//但不是全屏时获取原窗口的坐标和尺寸
Original_window_x = parentWidget->geometry().x();
Original_window_y = parentWidget->geometry().y();
Original_window_Mywidth = parentWidget->geometry().width();
Original_window_Myheight = parentWidget->geometry().height();
maxButton->setIcon(QPixmap("style/icons/normal.png"));
parentWidget->setGeometry(QApplication::desktop()->availableGeometry()); //这种设置不会全屏遮挡任务栏
}
}
/*************************** 最小化 ***************************/
void TitleBar::showMin()
{
parentWidget->showMinimized();
}
/*************************** 发送关闭信号给主窗口 ***************************/
void TitleBar::showClose()
{
emit send_close();
}
void TitleBar::set_ChildWindowColor(int R,int G,int B)
{
//设置背景色
setStyleSheet(QString("QFrame{background-color:rgb(%1,%2,%3);outline: none;border:none;}").arg(R).arg(G).arg(B));
}
//修改标题栏按钮提示语言
void TitleBar::ModifyTitleBarTip()
{
//设置鼠标移至按钮上的提示信息
minButton->setToolTip(tr(u8"最小化"));
maxButton->setToolTip(tr(u8"最大化"));
closeButton->setToolTip(tr(u8"关闭"));
}
/*************************** 鼠标点击 ***************************/
void TitleBar::mousePressEvent(QMouseEvent *event)
{
if(event->button() == Qt::LeftButton)
{
isLeftPressDown = true;
if (isTitleBarResize)
setMousePressCursorShape(event->pos());
if (dir != NONE) {
this->mouseGrabber();
}
else {
movePoint = event->globalPos() - parentWidget->pos();
}
}
}
/************************** 鼠标释放 ***************************/
void TitleBar::mouseReleaseEvent(QMouseEvent *event)
{
if (event->button() == Qt::LeftButton) {
isLeftPressDown = false;
if (dir != NONE) {
dir = NONE;
this->releaseMouse();
this->setCursor(QCursor(Qt::ArrowCursor));
}
}
}
/************************** 鼠标移动 **************************/
void TitleBar::mouseMoveEvent(QMouseEvent *event)
{
if(parentWidget->geometry() == QApplication::desktop()->availableGeometry())
{
//判断当前是全屏就不允许拖动窗口
}
else
{
//当前不是全屏可以拖动窗口
QPoint gloPoint = event->globalPos();
QRect rect = parentWidget->rect();
QPoint tl = mapToGlobal(rect.topLeft());
QPoint rb = mapToGlobal(rect.bottomRight());
if (!isLeftPressDown) {
if (isTitleBarResize)
setMousePressCursorShape(gloPoint);
}
else {
if (dir != NONE) {
QRect rMove(tl, rb);
switch (dir) {
case LEFT:
if (rb.x() - gloPoint.x() <= parentWidget->minimumWidth())
rMove.setX(tl.x());
else
rMove.setX(gloPoint.x());
break;
case RIGHT:
rMove.setWidth(gloPoint.x() - tl.x());
break;
case UP:
if (rb.y() - gloPoint.y() <= parentWidget->minimumHeight())
rMove.setY(tl.y());
else
rMove.setY(gloPoint.y());
break;
case LEFTTOP:
if (rb.x() - gloPoint.x() <= parentWidget->minimumWidth())
rMove.setX(tl.x());
else
rMove.setX(gloPoint.x());
if (rb.y() - gloPoint.y() <= parentWidget->minimumHeight())
rMove.setY(tl.y());
else
rMove.setY(gloPoint.y());
break;
case RIGHTTOP:
rMove.setWidth(gloPoint.x() - tl.x());
if (rb.y() - gloPoint.y() <= parentWidget->minimumHeight())
rMove.setY(tl.y());
else
rMove.setY(gloPoint.y());
break;
default:
break;
}
parentWidget->setGeometry(rMove);
}
else {
QPoint movePos = event->globalPos();
parentWidget->move(movePos - movePoint);
event->accept();
}
}
}
}
/************************** 鼠标双击 **************************/
void TitleBar::mouseDoubleClickEvent(QMouseEvent *event)
{
if(event->button() == Qt::LeftButton)
{
if(MaximizeFlag == 1)
{
int x = event->x();
int y = event->y();
if((x > 0 && x < parentWidget->width()) && (y > 0 && y < TITLEBARHEIGHT)) //如果双击的范围在标题栏的范围之内
{
showMax(); //调用全屏、退出全屏函数
}
}
}
}
bool TitleBar::eventFilter(QObject * obj, QEvent * event)
{
if (obj == this)
{
if (event->type() == QMouseEvent::HoverEnter)
{
QMouseEvent *_mouseEvent = static_cast<QMouseEvent *>(event);
if (isTitleBarResize)
setMousePressCursorShape(_mouseEvent->pos(), false);
}
if (event->type() == QMouseEvent::HoverMove)
{
QMouseEvent *_mouseEvent = static_cast<QMouseEvent *>(event);
if (!isLeftPressDown)
{
if (isTitleBarResize)
setMousePressCursorShape(_mouseEvent->pos(), false);
}
}
if (event->type() == QMouseEvent::HoverLeave)
{
if (isTitleBarResize)
unsetCursor();
}
}
return QFrame::eventFilter(obj, event);
}
void TitleBar::Set_MouseShapeFlag(bool MouseShape)
{
isTitleBarResize = MouseShape;
}
QRectF TitleBar::boundingRect() const
{
return QRectF(QPointF(0, 0), geometry().size());
}
QRectF TitleBar::leftBorder() const
{
return QRectF(0, 0, PADDING, boundingRect().height());
}
QRectF TitleBar::rightBorder() const
{
return QRectF(boundingRect().width() - PADDING, 0, PADDING, boundingRect().height());
}
QRectF TitleBar::topBorder() const
{
return QRectF(0, 0, boundingRect().width(), PADDING);
}
QRectF TitleBar::bottomBorder() const
{
return QRectF(0, boundingRect().height() - PADDING, boundingRect().width(), PADDING);
}
void TitleBar::setMousePressCursorShape(const QPointF& pt, bool isShow)
{
QCursor cursor = Qt::ArrowCursor;
if (rightBorder().contains(pt) && topBorder().contains(pt)) // 右上角
{
if(isShow)
dir = RIGHTTOP;
this->setCursor(QCursor(Qt::SizeBDiagCursor));
}
else if (leftBorder().contains(pt) && topBorder().contains(pt)) // 左上角
{
if (isShow)
dir = LEFTTOP;
this->setCursor(QCursor(Qt::SizeFDiagCursor));
}
else if (rightBorder().contains(pt)) // 右边
{
if (isShow)
dir = RIGHT;
this->setCursor(QCursor(Qt::SizeHorCursor));
}
else if (leftBorder().contains(pt)) // 左边
{
if (isShow)
dir = LEFT;
this->setCursor(QCursor(Qt::SizeHorCursor));
}
else if (topBorder().contains(pt)) // 上边
{
if (isShow)
dir = UP;
this->setCursor(QCursor(Qt::SizeVerCursor));
}
else
{
if (isShow)
dir = NONE;
this->setCursor(QCursor(isLeftPressDown ? Qt::SizeAllCursor : Qt::ArrowCursor));
}
}
// 绘制事件中设置标题栏宽度跟随父窗口宽度变化尺寸
void TitleBar::paintEvent(QPaintEvent *event)
{
if (this->width() != parentWidget->width())
{
this->setFixedWidth(parentWidget->width());
}
QFrame::paintEvent(event);
}
//自定义标题栏
{
Main_InterfaceTitleBar = new TitleBar(this); //在.h头文件中TitleBar *Main_InterfaceTitleBar
setWindowFlags(Qt::FramelessWindowHint | Qt::Dialog); //设置为无边框
connect(Main_InterfaceTitleBar, &TitleBar::send_close, this, [=]() {close();}); //一般窗口就是关闭,主界面或登录界面就是退出软件
Main_InterfaceTitleBar->Set_MaximizeFlag(); //设置是否有最大最小化按钮
Main_InterfaceTitleBar->setFixedHeight(40); //设置标题栏高度
Main_InterfaceTitleBar->Set_MouseShapeFlag(true); //设置是否可以改变窗口大小
Main_InterfaceTitleBar->setWindowIcon(":/trayIcon.png"); //这里根据自己的图标路径填写
Main_InterfaceTitleBar->setWindowTitle(tr("图像拼接处理器")); //设置标题栏标题
}
//布局情况很多种,标题栏只是显示在父窗口最上面的位置,具体怎么调整根据自己的布局来设置
QVBoxLayout *vlayout = new QVBoxLayout;
vlayout->addWidget(LargeScreenTitleBar);
vlayout->addLayout(...);
vlayout->addWidget(...);
vlayout->addWidget(...);
vLayout->setContentsMargins(0, 0, 0, 0);
setLayout(vlayout);
可根据自己需求添加删除按钮,调整标题栏大小。