Qt如何实现自定义标题栏
Qt 中实现自定义标题栏的关键是:
1️⃣ 先去掉系统默认标题栏和边框。
2️⃣ 使用自绘的 QWidget/QFrame 作为标题栏,自己实现拖动、双击最大化、最小化/关闭按钮等逻辑。
下面给你一个详细的实现步骤 + 可直接用的示例代码(Qt5/Qt6 通用):
完整示例下载地址:https://download.csdn.net/download/2501_91893428/91967952
1️⃣ 实现步骤
(1) 去掉系统默认标题栏
使用 Qt::FramelessWindowHint
去掉默认边框:
setWindowFlags(Qt::FramelessWindowHint | Qt::Window);
⚠️ 这样窗口没有系统边框,拖动、缩放、阴影都需要自己实现。
(2) 自定义标题栏
用一个 QWidget
(或 QFrame
)作为标题栏容器,可以放置:
-
窗口标题文本(
QLabel
) -
最小化 / 最大化 / 关闭按钮(
QPushButton
或QToolButton
)
(3) 实现拖动窗口
重写 mousePressEvent
、mouseMoveEvent
:
-
按下时记录鼠标位置
-
移动时计算偏移量并调用
move()
移动窗口。
(4) 双击最大化/还原
重写 mouseDoubleClickEvent
,双击标题栏切换 showMaximized()
/ showNormal()
。
(5) 自定义按钮功能
-
最小化:
showMinimized()
-
最大化:
isMaximized() ? showNormal() : showMaximized()
-
关闭:
close()
2️⃣ 完整示例(Qt Widgets)
MainWindow.h
#pragma once
#include <QWidget>
#include <QMouseEvent>class MainWindow : public QWidget
{Q_OBJECT
public:explicit MainWindow(QWidget *parent = nullptr);
protected:void mousePressEvent(QMouseEvent *event) override;void mouseMoveEvent(QMouseEvent *event) override;
private:QPoint m_dragPosition;
};
MainWindow.cpp
#include "MainWindow.h"
#include <QHBoxLayout>
#include <QLabel>
#include <QPushButton>
#include <QApplication>MainWindow::MainWindow(QWidget *parent) : QWidget(parent)
{setWindowFlags(Qt::FramelessWindowHint | Qt::Window); // 无边框setMinimumSize(600, 400);// ---- 自定义标题栏 ----QWidget *titleBar = new QWidget(this);titleBar->setFixedHeight(35);titleBar->setStyleSheet("background-color:#444; color:white;");QLabel *title = new QLabel("自定义标题栏窗口");QPushButton *btnMin = new QPushButton("-");QPushButton *btnMax = new QPushButton("□");QPushButton *btnClose = new QPushButton("×");for (auto btn : {btnMin, btnMax, btnClose}) {btn->setFixedSize(30, 30);btn->setStyleSheet("QPushButton {border:none; color:white;} ""QPushButton:hover {background:#666;}");}QHBoxLayout *titleLayout = new QHBoxLayout(titleBar);titleLayout->setContentsMargins(5, 0, 5, 0);titleLayout->addWidget(title);titleLayout->addStretch();titleLayout->addWidget(btnMin);titleLayout->addWidget(btnMax);titleLayout->addWidget(btnClose);// ---- 中心内容 ----QLabel *content = new QLabel("这里是主内容区域");content->setAlignment(Qt::AlignCenter);QVBoxLayout *mainLayout = new QVBoxLayout(this);mainLayout->setContentsMargins(1, 1, 1, 1);mainLayout->addWidget(titleBar);mainLayout->addWidget(content, 1);// ---- 按钮信号 ----connect(btnMin, &QPushButton::clicked, this, &QWidget::showMinimized);connect(btnMax, &QPushButton::clicked, [=] {isMaximized() ? showNormal() : showMaximized();});connect(btnClose, &QPushButton::clicked, this, &QWidget::close);
}void MainWindow::mousePressEvent(QMouseEvent *event)
{if (event->button() == Qt::LeftButton) {m_dragPosition = event->globalPos() - frameGeometry().topLeft();event->accept();}
}void MainWindow::mouseMoveEvent(QMouseEvent *event)
{if (event->buttons() & Qt::LeftButton) {move(event->globalPos() - m_dragPosition);event->accept();}
}
main.cpp
#include "MainWindow.h"
#include <QApplication>int main(int argc, char *argv[])
{QApplication a(argc, argv);MainWindow w;w.show();return a.exec();
}
3️⃣ 进阶功能
-
窗口阴影:
-
Windows:使用
QGraphicsDropShadowEffect
。 -
Mac/Linux:可用
Qt::FramelessWindowHint
+setAttribute(Qt::WA_TranslucentBackground)
。
-
-
可拉伸调整大小:
-
需检测鼠标靠近边框的区域,自行实现拉伸逻辑。
-
-
动画效果:
-
使用
QPropertyAnimation
实现平滑最小化/最大化。
-
总结
完整示例下载地址:https://download.csdn.net/download/2501_91893428/91967952
✅ 核心:去系统边框 + 自绘标题栏 + 处理拖动/按钮事件
✅ 优点:外观完全自定义,适合现代UI
✅ 缺点:需自行实现阴影、缩放、系统菜单等功能