当前位置: 首页 > news >正文

Qt之自定义标题栏拓展(十)

Qt开发 系列文章 - user-defined-titlebars(十)


目录

前言

一、方式一

1.效果演示

2.创建标题栏类

3.可视化UI设计

4.定义相关函数

5.使用标题栏类

二、方式二

1.效果演示

2.创建标题栏类

3.定义相关函数

1.初始化函数

2.功能函数

3.窗口关联

4.使用标题栏类

三、方式三

1.实现方式

2.效果演示

总结


前言

Qt自带的窗口标题栏通常遵循操作系统的默认样式和布局,以确保在不同平台上都能提供一致且符合用户期望的用户体验,因此Qt自带的窗口标题栏无法自定义。但我们在Qt设计软件时,经常需要改变窗口标题栏的样式,以满足不同场合用户需求。本文紧接着上一篇博文Qt之修改窗口标题、图标以及自定义标题栏(九)-CSDN博客的基础上,在介绍几种实现自定义标题栏的方法,并提供简单示例。


一、方式一

上一篇博文Qt之修改窗口标题、图标以及自定义标题栏(九)实现该方式是通过直接手鲁编写标题栏UI代码,下面提供的方式是在可视化界面UI上来设计标题栏,简洁方便直观,然后绑定/链接到主窗口界面上。

1.效果演示

2.创建标题栏类

跟上一个有区别的是,在原有的项目上,添加新的类文件,选择带ui设计类的模版,选择如下。

然后,定义类和ui的名称为MyTitleBar,MyTitleBar类的头文件代码如下(示例):

/** 只提供与上一篇不一样的代码地方 **/
QT_BEGIN_NAMESPACE
namespace Ui { class MyTitleBar; }
QT_END_NAMESPACEclass MyTitleBar : public QWidget
{
private slots:// 按钮触发的槽;void on_m_pButtonClose_clicked();void on_m_pButtonMax_clicked();void on_m_pButtonRestore_clicked();void on_m_pButtonMin_clicked();
private:Ui::MyTitleBar *ui;
};

3.可视化UI设计

上面我们定义标题栏类的头文件,下面来在可视化界面UI上来设计标题栏,双击打开.ui文件,在图像化设计界面设计如下标题栏。

  

上面设计完后,Qt会自动生成相应的UI代码和头文件,相关类为Ui_MyTitleBar。

4.定义相关函数

设计好MyTitleBar的UI文件后,下面来说明相关功能函数。

#include "ui_mytitlebar.h"
#include "mytitlebar.h"MyTitleBar::MyTitleBar(QWidget *parent): QWidget(parent), ui(new Ui::MyTitleBar)
{// UI初始化ui->setupUi(this);// 初始化控件initControl();// 初始化标题栏色彩setBackgroundColor(m_colorR, m_colorG, m_colorB, m_isTransparent);// 加载本地样式 .css文件//loadStyleSheet("MyTitle");// 初始化标题栏色彩setBackgroundColor(230,232,250,0);setStyleSheet("QToolButton#m_pButtonMenu,QPushButton#m_pButtonMin,QPushButton#m_pButtonMax,QPushButton#m_pButtonClose{\border-radius:3px;\color:#324C6C;\padding:3px;\margin:0px;\background:none;\border-style:none;\}");setStyleSheet("QToolButton#m_pButtonMenu:hover,QPushButton#m_pButtonMin:hover,QPushButton#m_pButtonMax:hover{\color:#FFFFFF;\margin:1px 1px 2px 1px;\background-color:rgba(51,127,209,230);\}");
}
MyTitleBar::~MyTitleBar()
{
}
void MyTitleBar::initControl()
{m_colorR=0;m_colorG=153;m_colorB=153;m_isPressed=false;m_buttonType=MIN_MAX_BUTTON;m_windowBorderWidth=0;m_isTransparent=false;setFixedHeight(30);setWindowFlags(Qt::FramelessWindowHint);// 添加换肤菜单QStringList name;name << "银色" << "蓝色" << "浅蓝色" << "深蓝色";foreach (QString str, name) {QAction *action = new QAction(str, this);ui->m_pButtonMenu->addAction(action);connect(action, SIGNAL(triggered(bool)), this, SLOT(onButtonchangeStyle()));}
}
// 以下为按钮操作响应的槽
void MyTitleBar::onButtonchangeStyle()
{QAction *act = (QAction *)sender();QString name = act->text();//QString qssFile = "qss/blue.css";if (name == "银色") {//qssFile = "qss/silvery.css";setBackgroundColor(230,232,250,0);}else if (name == "蓝色"){//qssFile = "qss/blue.css";setBackgroundColor(50,76,108,0);}else if (name == "浅蓝色"){//qssFile = "qss/lightblue.css";setBackgroundColor(56,100,135,0);}else if (name == "深蓝色"){//qssFile = "qss/darkblue.css";setBackgroundColor(122,175,227,0);}//loadStyleSheet(qssFile);//emit signalchangeStyle(qssFile);
}
void MyTitleBar::on_m_pButtonClose_clicked()
{emit signalButtonCloseClicked();
}
void MyTitleBar::on_m_pButtonMax_clicked()
{ui->m_pButtonMax->setVisible(false);ui->m_pButtonRestore->setVisible(true);emit signalButtonMaxClicked();
}
void MyTitleBar::on_m_pButtonRestore_clicked()
{ui->m_pButtonRestore->setVisible(false);ui->m_pButtonMax->setVisible(true);emit signalButtonRestoreClicked();
}
void MyTitleBar::on_m_pButtonMin_clicked()
{emit signalButtonMinClicked();
}

5.使用标题栏类

在用户的构造函数上面添加对标题栏类的使用,跟上一篇博文一样。

二、方式二

方式一实现自定义标题栏时,定义一个标题栏类,在生成标题栏时,会覆盖原有的MenuBar和ToolBar,方式二改进后,修改标题栏不覆盖,效果如下。

1.效果演示

2.创建标题栏类

跟上一篇博文一样,在原有的项目上,添加C++新的类文件,选择如下。

然后定义标题栏类,代码部分如下(示例):

#include <QDialog>
#include <QMutex>class QLabel;
class QPushButton;
class QToolButton;
class QVBoxLayout;
class QHBoxLayout;
class QFrame;
class QSpacerItem;
class QLineEdit;
class QComboBox;
class QAbstractButton;
class QUIWidget : public QDialog#endif
{Q_OBJECTQ_ENUMS(Style)Q_PROPERTY(QString title READ getTitle WRITE setTitle)Q_PROPERTY(Qt::Alignment alignment READ getAlignment WRITE setAlignment)
public:explicit QUIWidget(QWidget *parent = 0);~QUIWidget();
public Q_SLOTS://设置主窗体void setMainWidget(QWidget *mainWidget);//设置部件图标void setIcon(QUIWidget::Widget widget, QChar str, quint32 size = 9);//设置部件图片void setPixmap(QUIWidget::Widget widget, const QString &file, const QSize &size = QSize(16, 16));//设置部件是否可见void setVisible(QUIWidget::Widget widget, bool visible = true);//设置只有关闭按钮void setOnlyCloseBtn();//设置标题栏高度void setTitleHeight(int height);//设置按钮统一宽度void setBtnWidth(int width);//设置标题及文本样式void setTitle(const QString &title);void setAlignment(Qt::Alignment alignment);
};

3.定义相关函数

1.初始化函数

在标题栏类构造函数上,初始化如下设置,代码如下。

QUIWidget::QUIWidget(QWidget *parent) : QDialog(parent)
{//定义标题栏字体文本编码this->setTranslator(":/qm/qt_zh_CN.qm");this->setCode();this->initControl();this->initForm();//设置标题栏标题
#ifdef csdsetTitle("**软件");
#elsesetTitle("csd演示版");
#endif//设置标题文本居中setAlignment(Qt::AlignCenter);//设置窗体可拖动大小setSizeGripEnabled(true);//设置换肤下拉菜单可见setVisible(QUIWidget::BtnMenu, true);//设置标题栏高度setTitleHeight(30);//设置按钮宽度setBtnWidth(30);//设置软件左上角图标--没有图标时显示图形字体setPixmap(QUIWidget::Lab_Ico, "ico/butterfly.ico", QSize(30,30));//默认样式风格bluesetStyle(":/qss/blue.css");QFont font;font.setPointSize(12);this->setFont(font);
}
void QUIWidget::initControl()
{this->setObjectName(QString::fromUtf8("QUIWidget"));this->resize(900, 750);verticalLayout1 = new QVBoxLayout(this);verticalLayout1->setSpacing(0);verticalLayout1->setContentsMargins(11, 11, 11, 11);verticalLayout1->setObjectName(QString::fromUtf8("verticalLayout1"));verticalLayout1->setContentsMargins(1, 1, 1, 1);widgetMain = new QWidget(this);widgetMain->setObjectName(QString::fromUtf8("widgetMain"));widgetMain->setStyleSheet(QString::fromUtf8(""));verticalLayout2 = new QVBoxLayout(widgetMain);verticalLayout2->setSpacing(0);verticalLayout2->setContentsMargins(11, 11, 11, 11);verticalLayout2->setObjectName(QString::fromUtf8("verticalLayout2"));verticalLayout2->setContentsMargins(0, 0, 0, 0);widget_title = new QWidget(widgetMain);widget_title->setObjectName(QString::fromUtf8("widget_title"));QSizePolicy sizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed);sizePolicy.setHorizontalStretch(0);sizePolicy.setVerticalStretch(0);sizePolicy.setHeightForWidth(widget_title->sizePolicy().hasHeightForWidth());widget_title->setSizePolicy(sizePolicy);widget_title->setMinimumSize(QSize(0, 30));horizontalLayout4 = new QHBoxLayout(widget_title);horizontalLayout4->setSpacing(0);horizontalLayout4->setContentsMargins(11, 11, 11, 11);horizontalLayout4->setObjectName(QString::fromUtf8("horizontalLayout4"));horizontalLayout4->setContentsMargins(0, 0, 0, 0);lab_Ico = new QLabel(widget_title);lab_Ico->setObjectName(QString::fromUtf8("lab_Ico"));QSizePolicy sizePolicy1(QSizePolicy::Minimum, QSizePolicy::Preferred);sizePolicy1.setHorizontalStretch(0);sizePolicy1.setVerticalStretch(0);sizePolicy1.setHeightForWidth(lab_Ico->sizePolicy().hasHeightForWidth());lab_Ico->setSizePolicy(sizePolicy1);lab_Ico->setMinimumSize(QSize(30, 0));lab_Ico->setAlignment(Qt::AlignCenter);horizontalLayout4->addWidget(lab_Ico);lab_Title = new QLabel(widget_title);lab_Title->setObjectName(QString::fromUtf8("lab_Title"));QSizePolicy sizePolicy2(QSizePolicy::Expanding, QSizePolicy::Preferred);sizePolicy2.setHorizontalStretch(0);sizePolicy2.setVerticalStretch(0);sizePolicy2.setHeightForWidth(lab_Title->sizePolicy().hasHeightForWidth());lab_Title->setSizePolicy(sizePolicy2);lab_Title->setAlignment(Qt::AlignLeading | Qt::AlignLeft | Qt::AlignVCenter);horizontalLayout4->addWidget(lab_Title);widget_menu = new QWidget(widget_title);widget_menu->setObjectName(QString::fromUtf8("widget_menu"));sizePolicy1.setHeightForWidth(widget_menu->sizePolicy().hasHeightForWidth());widget_menu->setSizePolicy(sizePolicy1);horizontalLayout = new QHBoxLayout(widget_menu);horizontalLayout->setSpacing(0);horizontalLayout->setContentsMargins(11, 11, 11, 11);horizontalLayout->setObjectName(QString::fromUtf8("horizontalLayout"));horizontalLayout->setContentsMargins(0, 0, 0, 0);btnMenu = new QToolButton(widget_menu);btnMenu->setObjectName(QString::fromUtf8("btnMenu"));QSizePolicy sizePolicy3(QSizePolicy::Fixed, QSizePolicy::Expanding);sizePolicy3.setHorizontalStretch(0);sizePolicy3.setVerticalStretch(0);sizePolicy3.setHeightForWidth(btnMenu->sizePolicy().hasHeightForWidth());btnMenu->setSizePolicy(sizePolicy3);btnMenu->setMinimumSize(QSize(30, 0));btnMenu->setMaximumSize(QSize(30, 16777215));btnMenu->setFocusPolicy(Qt::NoFocus);btnMenu->setPopupMode(QToolButton::InstantPopup);horizontalLayout->addWidget(btnMenu);btnMenu_Min = new QPushButton(widget_menu);btnMenu_Min->setObjectName(QString::fromUtf8("btnMenu_Min"));QSizePolicy sizePolicy4(QSizePolicy::Minimum, QSizePolicy::Expanding);sizePolicy4.setHorizontalStretch(0);sizePolicy4.setVerticalStretch(0);sizePolicy4.setHeightForWidth(btnMenu_Min->sizePolicy().hasHeightForWidth());btnMenu_Min->setSizePolicy(sizePolicy4);btnMenu_Min->setMinimumSize(QSize(30, 0));btnMenu_Min->setMaximumSize(QSize(30, 16777215));btnMenu_Min->setCursor(QCursor(Qt::ArrowCursor));btnMenu_Min->setFocusPolicy(Qt::NoFocus);horizontalLayout->addWidget(btnMenu_Min);btnMenu_Max = new QPushButton(widget_menu);btnMenu_Max->setObjectName(QString::fromUtf8("btnMenu_Max"));sizePolicy3.setHeightForWidth(btnMenu_Max->sizePolicy().hasHeightForWidth());btnMenu_Max->setSizePolicy(sizePolicy3);btnMenu_Max->setMinimumSize(QSize(30, 0));btnMenu_Max->setMaximumSize(QSize(30, 16777215));btnMenu_Max->setCursor(QCursor(Qt::ArrowCursor));btnMenu_Max->setFocusPolicy(Qt::NoFocus);horizontalLayout->addWidget(btnMenu_Max);btnMenu_Close = new QPushButton(widget_menu);btnMenu_Close->setObjectName(QString::fromUtf8("btnMenu_Close"));sizePolicy3.setHeightForWidth(btnMenu_Close->sizePolicy().hasHeightForWidth());btnMenu_Close->setSizePolicy(sizePolicy3);btnMenu_Close->setMinimumSize(QSize(30, 0));btnMenu_Close->setMaximumSize(QSize(30, 16777215));btnMenu_Close->setCursor(QCursor(Qt::ArrowCursor));btnMenu_Close->setFocusPolicy(Qt::NoFocus);horizontalLayout->addWidget(btnMenu_Close);horizontalLayout4->addWidget(widget_menu);verticalLayout2->addWidget(widget_title);widget = new QWidget(widgetMain);widget->setObjectName(QString::fromUtf8("widget"));verticalLayout3 = new QVBoxLayout(widget);verticalLayout3->setSpacing(0);verticalLayout3->setContentsMargins(11, 11, 11, 11);verticalLayout3->setObjectName(QString::fromUtf8("verticalLayout3"));verticalLayout3->setContentsMargins(0, 0, 0, 0);verticalLayout2->addWidget(widget);verticalLayout1->addWidget(widgetMain);connect(this->btnMenu_Min, SIGNAL(clicked(bool)), this, SLOT(on_btnMenu_Min_clicked()));connect(this->btnMenu_Max, SIGNAL(clicked(bool)), this, SLOT(on_btnMenu_Max_clicked()));connect(this->btnMenu_Close, SIGNAL(clicked(bool)), this, SLOT(on_btnMenu_Close_clicked()));
}void QUIWidget::initForm()
{//设置图形字体setIcon(QUIWidget::Lab_Ico, QChar(0xf099), 11); //设置左上角图标-图形字体setIcon(QUIWidget::BtnMenu, 0xf0d7);setIcon(QUIWidget::BtnMenu_Min, 0xf068);setIcon(QUIWidget::BtnMenu_Max, 0xf067);setIcon(QUIWidget::BtnMenu_Close, 0xf00d);//设置标题及对齐方式setTitle("QUI Demo");setAlignment(Qt::AlignLeft | Qt::AlignVCenter);setVisible(QUIWidget::BtnMenu, false);mainWidget = 0;max = false;location = this->geometry();this->setProperty("form", true);this->setWindowFlags(Qt::FramelessWindowHint | Qt::WindowSystemMenuHint | Qt::WindowMinMaxButtonsHint);//第一个参数是设置无边框。第二个参数是允许任务栏按钮右键菜单,第三个参数是允许最小化最大化与还原this->setWindowFlags(Qt::FramelessWindowHint);//任务栏单击图标后最小化后图标会消失,无法解决,因此不让最小化//绑定事件过滤器监听鼠标移动this->installEventFilter(this);this->widget_title->installEventFilter(this);//添加换肤菜单QStringList name;name << "银色" << "蓝色" << "浅蓝色" << "深蓝色" << "灰色" << "浅灰色" << "深灰色" << "黑色"<< "浅黑色" << "深黑色" << "PS黑色" << "黑色扁平" << "白色扁平" << "浅紫色" << "橙色";foreach (QString str, name) {QAction *action = new QAction(str, this);this->btnMenu->addAction(action);connect(action, SIGNAL(triggered(bool)), this, SLOT(changeStyle()));}
}

2.功能函数

具体设置部件图标、设置部件图片、设置部件是否可见、设置标题栏高度、设置按钮统一宽度、设置标题及文本样式等等设置,代码如下。

void QUIWidget::setIcon(QUIWidget::Widget widget, QChar str, quint32 size)
{if (widget == QUIWidget::Lab_Ico) {IconHelper::Instance()->setIcon(this->lab_Ico, str, size);} else if (widget == QUIWidget::BtnMenu) {IconHelper::Instance()->setIcon(this->btnMenu, str, size);} else if (widget == QUIWidget::BtnMenu_Min) {IconHelper::Instance()->setIcon(this->btnMenu_Min, str, size);} else if (widget == QUIWidget::BtnMenu_Max) {IconHelper::Instance()->setIcon(this->btnMenu_Max, str, size);} else if (widget == QUIWidget::BtnMenu_Close) {IconHelper::Instance()->setIcon(this->btnMenu_Close, str, size);}
}void QUIWidget::setPixmap(QUIWidget::Widget widget, const QString &file, const QSize &size)
{QPixmap pix = QPixmap(file);//按照宽高比自动缩放pix = pix.scaled(size, Qt::KeepAspectRatio);if (widget == QUIWidget::Lab_Ico) {this->lab_Ico->setPixmap(pix);} else if (widget == QUIWidget::BtnMenu) {this->btnMenu->setIcon(QIcon(file));} else if (widget == QUIWidget::BtnMenu_Min) {this->btnMenu_Min->setIcon(QIcon(file));} else if (widget == QUIWidget::BtnMenu_Max) {this->btnMenu_Max->setIcon(QIcon(file));} else if (widget == QUIWidget::BtnMenu_Close) {this->btnMenu_Close->setIcon(QIcon(file));}
}void QUIWidget::setVisible(QUIWidget::Widget widget, bool visible)
{if (widget == QUIWidget::Lab_Ico) {this->lab_Ico->setVisible(visible);} else if (widget == QUIWidget::BtnMenu) {this->btnMenu->setVisible(visible);} else if (widget == QUIWidget::BtnMenu_Min) {this->btnMenu_Min->setVisible(visible);} else if (widget == QUIWidget::BtnMenu_Max) {this->btnMenu_Max->setVisible(visible);} else if (widget == QUIWidget::BtnMenu_Close) {this->btnMenu_Close->setVisible(visible);}
}void QUIWidget::setOnlyCloseBtn()
{this->btnMenu->setVisible(false);this->btnMenu_Min->setVisible(false);this->btnMenu_Max->setVisible(false);
}void QUIWidget::setTitleHeight(int height)
{this->widget_title->setFixedHeight(height);
}void QUIWidget::setBtnWidth(int width)
{this->lab_Ico->setFixedWidth(width);this->btnMenu->setFixedWidth(width);this->btnMenu_Min->setFixedWidth(width);this->btnMenu_Max->setFixedWidth(width);this->btnMenu_Close->setFixedWidth(width);
}void QUIWidget::setTitle(const QString &title)
{if (this->title != title) {this->title = title;this->lab_Title->setText(title);this->setWindowTitle(this->lab_Title->text());}
}void QUIWidget::setAlignment(Qt::Alignment alignment)
{if (this->alignment != alignment) {this->alignment = alignment;this->lab_Title->setAlignment(alignment);}
}void QUIWidget::on_btnMenu_Min_clicked()
{this->showMinimized();
}void QUIWidget::on_btnMenu_Max_clicked()
{if (max) {this->setGeometry(location);} else {location = this->geometry();this->setGeometry(qApp->desktop()->availableGeometry());}max = !max;
}void QUIWidget::on_btnMenu_Close_clicked()
{close();
}

3.窗口关联

打开主函数文件,在Main函数上将主窗口(用户)链接到标题栏窗口上,关联起来,代码如下。

int main(int argc, char *argv[])
{QApplication a(argc, argv);//定义用户窗口MainWindow *w = new MainWindow;//定义标题栏QUIWidget qui;//将主窗体链接/关联到标题栏窗口上qui.setMainWidget(w);qui.show();return a.exec();
}
void QUIWidget::setMainWidget(QWidget *mainWidget)
{//一个QUI窗体对象只能设置一个主窗体if (this->mainWidget == 0) {//将子窗体添加到布局this->widget->layout()->addWidget(mainWidget);//自动设置大小resize(mainWidget->width(), mainWidget->height() + this->widget_title->height());this->mainWidget = mainWidget;this->mainWidget->installEventFilter(this);}
}

4.使用标题栏类

因为在Main函数上,已经将主窗体链接/关联到标题栏窗口上,因此在用户层无需关注/设置标题栏相关参数。这里和方式一不一样的是,方式是将标题栏类作为主窗口的私有变量使用,而方式二只是将两个窗口界面关联起来而已。

至此方式二讲解完毕,该种方式有个缺点是需要手鲁UI设计代码。更快捷的是,通过可视化界面UI来设计标题栏,然后绑定/链接到主窗口界面上,跟方式一一样。

三、方式三

方式三的实现方式不同于上述两种(需要创建具体标题栏类),而这种方式三是不需要的,只需要在原项目上的主窗口UI上,绘制一个标题栏,然后影藏主标题栏,显示绘制的标题栏,即可。具体实现示例见文末链接处,下面介绍下实现思路。

1.实现方式

打开原有项目的可视化UI设计文件,进行如下设计。

在重新绘制的标题栏上面有原项目保留的菜单栏,在程序构造函数将其隐藏即可,另将其关联到新建的菜单栏上,避免再绘制,具体代码如下。

MainWindow::MainWindow(QWidget *parent): QMainWindow(parent), ui(new Ui::MainWindow)
{ui->setupUi(this);this->setWindowTitle("我的窗口");/*** 隐藏原有的工具栏和菜单栏 ***/ui->toolBar->hide();ui->menubar->hide();setBtnHeight(26);InitChart();/*** 注册事件过滤器 ***/ui->widget->installEventFilter(this);ui->tab->installEventFilter(this);ui->tab_2->installEventFilter(this);// 注册只点击标题栏移动事件过滤器ui->horizontalWidget->installEventFilter(this);/*** 创建右键菜单 ***/CreateMenu(ui->widget);CreateMenu(ui->tab);CreateMenu(ui->tab_2);// 添加换肤菜单QStringList name;name << "浅蓝色" << "浅青色" << "浅灰色" << "浅灰色" << "浅红色" << "浅紫色" << "浅橙色";foreach (QString str, name) {QAction *action = new QAction(str, this);ui->toolButton->addAction(action);connect(action, SIGNAL(triggered(bool)), this, SLOT(onButtonchangeStyle()));}// 关联/添加到新的菜单栏上menubar = new QMenuBar(ui->horizontalWidget_2);menubar->setObjectName(QString::fromUtf8("menubar"));menubar->setGeometry(QRect(0, 0, 785, 23));menubar->addAction(ui->menu->menuAction());menubar->addAction(ui->menu_2->menuAction());menubar->addAction(ui->menu_3->menuAction());
}
void MainWindow::setBtnHeight(int Height)
{ui->label->setFixedHeight(Height);ui->label_2->setFixedHeight(Height);ui->toolButton->setFixedHeight(Height);ui->min->setFixedHeight(Height);ui->max->setFixedHeight(Height);ui->close->setFixedHeight(Height);
}
// 以下为按钮操作响应的槽
void MainWindow::onButtonchangeStyle()
{QAction *act = (QAction *)sender();QString name = act->text();if (name == "浅蓝色")setStyleSheet("background-color: rgb(193,210,240)");else if (name == "浅青色")setStyleSheet("background-color: rgb(173, 255, 196)");else if (name == "浅灰色")setStyleSheet("background-color: rgb(211, 211, 211)");else if (name == "浅灰色")setStyleSheet("background-color: rgb(192, 192, 192)");else if (name == "浅红色")setStyleSheet("background-color: rgb(255, 182, 193)");else if (name == "浅紫色")setStyleSheet("background-color: rgb(171, 145, 204)");else if (name == "浅橙色")setStyleSheet("background-color: rgb(254, 216, 177)");
}

以上完成重新标题栏的绘制和菜单栏的关联,但是窗口无法移动,下面在通过鼠标使窗口移动,实现如下。

void MainWindow::mousePressEvent(QMouseEvent *event)
{if(event->button() == Qt::LeftButton){whereismouse = event->pos();}
}
void MainWindow::mouseMoveEvent(QMouseEvent *event)
{if(event->buttons() == Qt::LeftButton){//当窗口最大化或最小化时也不进行触发if(MainWindow::isMaximized() || MainWindow::isMinimized())return;else {//当在按钮之类需要鼠标操作的地方不进行触发(防误触)if (ui->close->underMouse()||ui->max->underMouse()||ui->min->underMouse()) {}else {MainWindow::move(MainWindow::mapToGlobal(event->pos()-whereismouse));//移动}}}event->accept();
}

以上代码实现功能是点击窗口任意地方,整个窗口移动,若只需要点击标题栏使整个窗口移动,则需要将上述代码屏蔽,添加如下代码实现。

protected://void mousePressEvent(QMouseEvent *event) override;//void mouseMoveEvent(QMouseEvent *event) override;bool MainWindow::eventFilter(QObject *watched, QEvent *event)
{if(watched == ui->widget) {if(event->type() == QEvent::MouseButtonPress)menu_widget->exec(cursor().pos());  //菜单显示的位置跟随鼠标}/*** 点击标题栏移动 ***/else if (watched == ui->horizontalWidget) {QMouseEvent *pMouseEvent = (QMouseEvent*)event;if(pMouseEvent->button() == Qt::LeftButton)whereismouse = pMouseEvent->pos();if(pMouseEvent->buttons() == Qt::LeftButton){//当窗口最大化或最小化时也不进行触发if(MainWindow::isMaximized() || MainWindow::isMinimized())return 0;else {//当在按钮之类需要鼠标操作的地方不进行触发(防误触)if (ui->close->underMouse()||ui->max->underMouse()||ui->min->underMouse()) {}else {MainWindow::move(MainWindow::mapToGlobal(pMouseEvent->pos()-whereismouse));//移动}}}event->accept();}return QObject::eventFilter(watched, event);
}

2.效果演示

编译运行完效果如下。


总结

方式一:实现方式是在原项目上新建一个带UI的设计类,在新建UI上完成标题栏的绘制,然后将该类设置为原主窗口的私有变量;
方式二:实现方式是在原项目上新建一个不带UI的C++类,然后通过手鲁代码编写标题栏,然后在Main函数上将主窗口和标题栏窗口链接/关联起来;
方式三:实现方式是在原项目上的主窗口UI上,绘制一个标题栏,然后影藏主标题栏,显示绘制的标题栏;

博文中相应的工程代码Qt-Case.zip 利用Qt开发软件进行编的例程,为博文提供案例-CSDN文库。

相关文章:

Qt之自定义标题栏拓展(十)

Qt开发 系列文章 - user-defined-titlebars&#xff08;十&#xff09; 目录 前言 一、方式一 1.效果演示 2.创建标题栏类 3.可视化UI设计 4.定义相关函数 5.使用标题栏类 二、方式二 1.效果演示 2.创建标题栏类 3.定义相关函数 1.初始化函数 2.功能函数 3.窗口关…...

Verilog中initial的用法

在 Verilog 语言中&#xff0c;initial 语句用于在仿真开始时执行一次性初始化操作。它是顺序执行的&#xff0c;用来描述在仿真启动时立即运行的代码块&#xff0c;通常用于赋初值、生成波形或控制信号行为。 语法 initial begin // 语句1 // 语句2 ... end特点 只…...

(14)D-FINE网络,爆锤yolo系列

yolo过时了&#xff1f;传统的yolo算法在小目标检测方面总是不行&#xff0c;最新算法DEIM爆锤yolo&#xff0c;已经替yolo解决。 一、创新点 ​ 这个算法名为DEIM&#xff0c;全称是DETR with Improved Matching for Fast Convergence&#xff0c;其主要创新点在于提出了一…...

Python :冬至快乐

第1部分&#xff1a;基础设置 首先创建一个新的 Python 文件&#xff0c;命名为 fireworks.py。 步骤 1.1: 导入必要的库 import pygame import random import sys from pygame.locals import * import math import time这些库的作用&#xff1a; pygame: 用于创建游戏和图…...

重拾设计模式--状态模式

文章目录 状态模式&#xff08;State Pattern&#xff09;概述状态模式UML图作用&#xff1a;状态模式的结构环境&#xff08;Context&#xff09;类&#xff1a;抽象状态&#xff08;State&#xff09;类&#xff1a;具体状态&#xff08;Concrete State&#xff09;类&#x…...

稀疏矩阵的存储与计算 gaxpy

1, gaxpy 数学公式 其中&#xff1a; &#xff0c; &#xff0c; 2, 具体实例 3&#xff0c;用稠密矩阵的方法 本节将用于验证第4节中的稀疏计算的结果 hello_gaxpy_dense.cpp #include <stdio.h> #include <stdlib.h>struct Matrix_SP {float* val; //…...

基于LabVIEW的USRP信道测量开发

随着无线通信技术的不断发展&#xff0c;基于软件无线电的设备&#xff08;如USRP&#xff09;在信道测量、无线通信测试等领域扮演着重要角色。通过LabVIEW与USRP的结合&#xff0c;开发者可以实现信号生成、接收及信道估计等功能。尽管LabVIEW提供了丰富的信号处理工具和图形…...

基于LSTM长短期记忆神经网络的多分类预测【MATLAB】

在深度学习中&#xff0c;长短期记忆网络&#xff08;LSTM, Long Short-Term Memory&#xff09;是一种强大的循环神经网络&#xff08;RNN&#xff09;变体&#xff0c;专门为解决序列数据中的长距离依赖问题而设计。LSTM因其强大的记忆能力&#xff0c;广泛应用于自然语言处理…...

物联网:全面概述、架构、应用、仿真工具、挑战和未来方向

中文论文标题&#xff1a;物联网&#xff1a;全面概述、架构、应用、仿真工具、挑战和未来方向 英文论文标题&#xff1a;Internet of Things: a comprehensive overview, architectures, applications, simulation tools, challenges and future directions 作者信息&#x…...

volatility2工具的使用vol2工具篇

vol2工具 命令格式&#xff1a;vol.py -f [image] --profile[profile] [plugin] 1、查看系统的操作版本&#xff0c;系统镜像信息 2.查看用户名密码信息&#xff0c;当前操作系统中的password hash&#xff0c;例如SAM文件内容 3.从注册表提取LSA密钥信息&#xff08;已解密&…...

R 基础运算

R 基础运算 R 是一种广泛使用的统计编程语言&#xff0c;它提供了强大的数据操作和分析功能。基础运算在 R 中非常重要&#xff0c;因为它们是进行更复杂计算和数据分析的基础。本文将详细介绍 R 中的基础运算&#xff0c;包括算术运算、逻辑运算、向量化和矩阵运算。 一、算…...

javaScriptBOM

1.1、BOM概述 1.1.1、BOM简介 BOM&#xff08;browser Object&#xff09;即浏览器对象模型&#xff0c;它提供了独立于内容而与浏览器窗口进行交互的对象&#xff0c;其核心对象是window。 BOM由一系列的对象构成&#xff0c;并且每个对象都提供了很多方法与属性 BOM缺乏标准…...

Godot RPG 游戏开发指南

Godot RPG 游戏开发指南 一、基础准备 1. 开发环境 下载并安装最新版 Godot 4.x选择使用 GDScript 或 C# 作为开发语言准备基础美术资源&#xff08;角色、地图、道具等&#xff09; 2. 项目结构 project/ ├── scenes/ # 场景文件 ├── scripts/ # 脚…...

目标检测数据集图片及标签同步旋转角度

前言 在深度学习领域&#xff0c;尤其是目标检测任务中&#xff0c;数据集的质量直接影响模型的性能。为了提升模型的鲁棒性和对各种场景的适应能力&#xff0c;数据增强技术被广泛应用于图像数据集处理。旋转角度是常见的数据增强方法&#xff0c;通过对图像及其对应的标签&am…...

2025前端面试热门题目——计算机网络篇

计算机网络篇——面试 1. 到底什么是 TCP 连接? TCP 连接的定义 TCP&#xff08;传输控制协议&#xff09;是一个面向连接的传输层协议。TCP 连接是通过 三次握手 确立的可靠数据通信链路&#xff0c;保证了在不可靠网络&#xff08;如互联网&#xff09;上的数据传输的准确…...

LEAST-TO-MOST PROMPTING ENABLES COMPLEX REASONING IN LARGE LANGUAGE MODELS---正文

题目 最少到最多的提示使大型语言模型能够进行复杂的推理 论文地址&#xff1a;https://arxiv.org/abs/2205.10625 摘要 思路链提示在各种自然语言推理任务中表现出色。然而&#xff0c;它在需要解决比提示中显示的示例更难的问题的任务上表现不佳。为了克服这种由易到难的概括…...

Java开发经验——日志治理经验

摘要 本文主要介绍了Java开发中的日志治理经验&#xff0c;包括系统异常日志、接口摘要日志、详细日志和业务摘要日志的定义和目的&#xff0c;以及错误码规范和异常处理规范。强调了日志治理的重要性和如何通过规范化错误码和日志格式来提高系统可观测性和问题排查效率。 1. …...

使用复数类在C#中轻松绘制曼德布洛集分形

示例在 C# 中绘制曼德布洛特集分形解释了如何通过迭代以下方程来绘制曼德布洛特集&#xff1a; 其中 Z(n) 和 C 是复数。程序迭代此方程&#xff0c;直到 Z(n) 的大小至少为 2 或程序执行最大迭代次数。 该示例在单独的变量中跟踪数字的实部和虚部。此示例使用Complex类来更轻松…...

VSCode 启用免费 Copilot

升级VSCode到 1.96版本&#xff0c;就可以使用每个月2000次免费额度了&#xff0c;按照工作日每天近80次免费额度&#xff0c;满足基本需求。前两天一直比较繁忙&#xff0c;今天周六有时间正好体验一下。 引导插件安装GitHub Copilot - Visual Studio Marketplace Extension f…...

常见问题整理

DevOps 和 CICD DevOps 全称Development & Operation 一种实现开发和运维一体化的协同模式&#xff0c;提供快速交付应用和服务的能力 用于协作&#xff1a;开发&#xff0c;部署&#xff0c;质量测试 整体生命周期工作内容&#xff0c;最终实现持续继承&#xff0c;持续部…...

【Axure高保真原型】引导弹窗

今天和大家中分享引导弹窗的原型模板&#xff0c;载入页面后&#xff0c;会显示引导弹窗&#xff0c;适用于引导用户使用页面&#xff0c;点击完成后&#xff0c;会显示下一个引导弹窗&#xff0c;直至最后一个引导弹窗完成后进入首页。具体效果可以点击下方视频观看或打开下方…...

SciencePlots——绘制论文中的图片

文章目录 安装一、风格二、1 资源 安装 # 安装最新版 pip install githttps://github.com/garrettj403/SciencePlots.git# 安装稳定版 pip install SciencePlots一、风格 简单好用的深度学习论文绘图专用工具包–Science Plot 二、 1 资源 论文绘图神器来了&#xff1a;一行…...

23-Oracle 23 ai 区块链表(Blockchain Table)

小伙伴有没有在金融强合规的领域中遇见&#xff0c;必须要保持数据不可变&#xff0c;管理员都无法修改和留痕的要求。比如医疗的电子病历中&#xff0c;影像检查检验结果不可篡改行的&#xff0c;药品追溯过程中数据只可插入无法删除的特性需求&#xff1b;登录日志、修改日志…...

大型活动交通拥堵治理的视觉算法应用

大型活动下智慧交通的视觉分析应用 一、背景与挑战 大型活动&#xff08;如演唱会、马拉松赛事、高考中考等&#xff09;期间&#xff0c;城市交通面临瞬时人流车流激增、传统摄像头模糊、交通拥堵识别滞后等问题。以演唱会为例&#xff0c;暖城商圈曾因观众集中离场导致周边…...

Java 加密常用的各种算法及其选择

在数字化时代&#xff0c;数据安全至关重要&#xff0c;Java 作为广泛应用的编程语言&#xff0c;提供了丰富的加密算法来保障数据的保密性、完整性和真实性。了解这些常用加密算法及其适用场景&#xff0c;有助于开发者在不同的业务需求中做出正确的选择。​ 一、对称加密算法…...

2025季度云服务器排行榜

在全球云服务器市场&#xff0c;各厂商的排名和地位并非一成不变&#xff0c;而是由其独特的优势、战略布局和市场适应性共同决定的。以下是根据2025年市场趋势&#xff0c;对主要云服务器厂商在排行榜中占据重要位置的原因和优势进行深度分析&#xff1a; 一、全球“三巨头”…...

vulnyx Blogger writeup

信息收集 arp-scan nmap 获取userFlag 上web看看 一个默认的页面&#xff0c;gobuster扫一下目录 可以看到扫出的目录中得到了一个有价值的目录/wordpress&#xff0c;说明目标所使用的cms是wordpress&#xff0c;访问http://192.168.43.213/wordpress/然后查看源码能看到 这…...

抽象类和接口(全)

一、抽象类 1.概念&#xff1a;如果⼀个类中没有包含⾜够的信息来描绘⼀个具体的对象&#xff0c;这样的类就是抽象类。 像是没有实际⼯作的⽅法,我们可以把它设计成⼀个抽象⽅法&#xff0c;包含抽象⽅法的类我们称为抽象类。 2.语法 在Java中&#xff0c;⼀个类如果被 abs…...

mac:大模型系列测试

0 MAC 前几天经过学生优惠以及国补17K入手了mac studio,然后这两天亲自测试其模型行运用能力如何&#xff0c;是否支持微调、推理速度等能力。下面进入正文。 1 mac 与 unsloth 按照下面的进行安装以及测试&#xff0c;是可以跑通文章里面的代码。训练速度也是很快的。 注意…...

Python爬虫实战:研究Restkit库相关技术

1. 引言 1.1 研究背景与意义 在当今信息爆炸的时代,互联网上存在着海量的有价值数据。如何高效地采集这些数据并将其应用于实际业务中,成为了许多企业和开发者关注的焦点。网络爬虫技术作为一种自动化的数据采集工具,可以帮助我们从网页中提取所需的信息。而 RESTful API …...