重构了代码,将所有功能全部封装在容器类中,使用接口函数初始化标题栏。
1 2 3 4
| wrapper = new WrapperWidget();
wrapper->iniTitleBar(this);
|
熟悉win32编程的都知道,在注册窗口类时windows系统会提供一个标题栏,在不同的主题下风格都不一样。但是不能修改样式和添加功能。
自定义标题栏只有去掉系统标题栏,自己实现,尽量除了样式之外其他功能都要实现。
步骤

遇到的问题
因为主程序和标题栏都是容器类的子对象,在关闭程序时直接调用容器类的close()函数,不会发生内存泄露。
这个容器类是必须的,如果直接拿主窗口当容器,那么代码都要写在另一个子类里
标题栏的布局,设置标题栏的SizePolicy固定高度。中间的空隙用QSS的border属性清除。
QT自动释放内存机制
引用自知乎
main函数里面main widget/dialog/mainWindow是分配在栈上的,其他new出来的东西都以这个widget作为父亲。 当程序最后结束了,main widget弹栈。父类被销毁。子类跟着被销毁。 所以如果你自己new 出来的。没有父类,不删除就会造成内存泄漏。
源码
main.cpp
1 2 3 4 5 6 7 8 9 10
| #include "DesktopTools.h" #include <QtWidgets/QApplication>
int main(int argc, char *argv[]){ QApplication a(argc, argv); DesktopTools w; w.show(); return a.exec(); }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
| #pragma once
#include <QtWidgets/QMainWindow> #include "ui_DesktopTools.h" #include <QStyle> #include "CustomBar.h" #include <QGridLayout> #include <QPainter> #include <QPixmap> #include <QPaintEvent> #include <QEvent> #include <QPoint>
class DesktopTools : public QMainWindow{ Q_OBJECT
public: DesktopTools(QWidget *parent = Q_NULLPTR); ~DesktopTools();
private: Ui::DesktopToolsClass ui;
WrapperWidget *wrapper;
void iniUi(); void iniConnect();
protected: void paintEvent(QPaintEvent *event)override;
};
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41
| #include "DesktopTools.h"
DesktopTools::DesktopTools(QWidget *parent) : QMainWindow(parent) { ui.setupUi(this); iniUi(); iniConnect(); }
DesktopTools::~DesktopTools() { }
void DesktopTools::iniUi() { setWindowFlags(Qt::FramelessWindowHint); setStyleSheet(QString("\ #DesktopToolsClass{\ border:none;}"));
wrapper = new WrapperWidget();
wrapper->iniTitleBar(this);
}
void DesktopTools::iniConnect() { }
void DesktopTools::paintEvent(QPaintEvent *event) { QPainter mPainter(this); mPainter.drawPixmap(QRect(0, 0, this->width(), this->height()), QPixmap(":/DesktopTools/Resources/1FR3114501-1.jpg")); }
|
CustomBar.h
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67
| #pragma once #include <QtWidgets/QWidget> #include "ui_CustomBar.h" #include <QString> #include <QPaintEvent> #include <QPainter> #include <QHBoxlayout> #include <QEvent> #include <QGridLayout>
class CustomBar : public QWidget{ Q_OBJECT public: CustomBar(QWidget *parent = nullptr); private: Ui::CustomBarClass ui; void iniUi(); void iniConnect();
QHBoxLayout *hLayout; private slots: void onBtnCloseClicked();
signals: void btnCloseClicked(); void doubleClicked();
protected: void paintEvent(QPaintEvent *event)override;
};
class WrapperWidget : public QWidget { Q_OBJECT public:
explicit WrapperWidget(QWidget *parent = nullptr); ~WrapperWidget();
void iniTitleBar(QWidget *widget);
private: CustomBar *customBar; QGridLayout *tLayout; QPoint *currentWindowPos;
void iniUi(); void iniConnect();
private slots: void onBtnCloseClicked();
protected: bool eventFilter(QObject *obj, QEvent *event)override;
};
|
CustomBar.cpp
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159
| #include "CustomBar.h"
CustomBar::CustomBar(QWidget *parent) :QWidget(parent) { ui.setupUi(this); iniUi(); iniConnect(); }
void CustomBar::iniUi() { setWindowFlag(Qt::FramelessWindowHint); setWindowOpacity(0.5); setStyleSheet(QString("#CustomBarClass{\ background-color:rgba(0,0,0,0.5);\ border:none;}\ QPushButton{\ border:none;\ background-color:pink;\ }\ QPushButton::hover{\ background-color:red;}\ #mTitleLabel{color:white;}\ ")); ui.btnClose->setFixedSize(32, 32); ui.mTitleLabel->setText(QString(QStringLiteral("自定义标题栏示例 ...btkrc")));
setAttribute(Qt::WA_StyledBackground);
this->setMinimumHeight(40);
hLayout = new QHBoxLayout(this);
hLayout->addWidget(ui.mTitleLabel); hLayout->addWidget(ui.btnClose);
}
void CustomBar::iniConnect() { QObject::connect(ui.btnClose, SIGNAL(clicked()), this, SLOT(onBtnCloseClicked())); }
void CustomBar::paintEvent(QPaintEvent *event) { return QWidget::paintEvent(event); }
void CustomBar::onBtnCloseClicked() { emit btnCloseClicked(); }
WrapperWidget::WrapperWidget(QWidget *parent) :QWidget(parent) { iniUi(); iniConnect(); }
WrapperWidget::~WrapperWidget(){ delete currentWindowPos; }
void WrapperWidget::iniTitleBar(QWidget *widget) { tLayout->addWidget(widget, 1, 0, 1, 1); widget->setParent(this);
this->show(); }
void WrapperWidget::onBtnCloseClicked() { this->close(); }
void WrapperWidget::iniUi(){ currentWindowPos = new QPoint();
setWindowFlags(Qt::FramelessWindowHint);
resize(600, 400); setAttribute(Qt::WA_TranslucentBackground);
customBar = new CustomBar(this); customBar->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
customBar->installEventFilter(this);
customBar->setParent(this);
tLayout = new QGridLayout(this); tLayout->setSpacing(0); tLayout->setContentsMargins(0, 0, 0, 0); tLayout->addWidget(customBar, 0, 0, 1, 1); }
void WrapperWidget::iniConnect(){ QObject::connect(customBar, SIGNAL(btnCloseClicked()), this, SLOT(onBtnCloseClicked())); }
bool WrapperWidget::eventFilter(QObject *obj, QEvent *event) { if (obj == customBar) { switch (event->type()) { case QEvent::MouseButtonDblClick: {
QMouseEvent *mouseEvent = static_cast<QMouseEvent *>(event); if (mouseEvent->buttons() & Qt::LeftButton) { if (Qt::WindowMaximized == this->windowState()) { this->showNormal(); } else { this->showMaximized(); } } return true; } case QEvent::MouseButtonPress: { QMouseEvent *mouseEvent = static_cast<QMouseEvent *>(event); *currentWindowPos = mouseEvent->pos(); return true; } case QEvent::MouseMove: { QMouseEvent *mouseEvent = static_cast<QMouseEvent *>(event); if (mouseEvent->buttons() & Qt::LeftButton) { this->move(mouseEvent->globalPos() - *currentWindowPos); return true; } else return false; } default: { return false; } } } else { return QWidget::eventFilter(obj, event); } }
|