QT5.14.2解锁Qt自定义标题栏的无限可能,一键拥有与众不同的个性窗口!

在现代化的软件设计中,个性化和美观是应用程序界面不可或缺的元素。而传统的Qt窗口往往风格单一,标题栏固定死板,这严重限制了界面的灵活性和视觉体验。有没有一种方法,可以摆脱这些束缚,为我们的Qt应用注入无限活力?今天,我们就来探索自定义Qt标题栏的奥秘,打造属于你自己的曲线玲珑、别具一格的窗口王冠!

一、Qt自定义标题栏的优势

相比于使用Qt默认的标题栏,自定义标题栏有以下显著优势:

  1. 无限个性化:可自由设计标题栏的外观、布局、控件等,实现与众不同的风格。

  2. 跨平台统一:在不同操作系统下,标题栏界面保持一致,提升应用的整体性。

  3. 功能扩展性强:可方便地添加自定义按钮、搜索框等新功能,提高用户体验。

二、标题栏组件拆解

要实现自定义标题栏,我们需要自行构建其各个组成部分,包括:

  • 标题文字:用于显示应用程序名称或当前窗口标题
  • 窗口控制按钮:最小化、最大化/恢复、关闭按钮
  • 拖动区域:用于实现整个窗口的拖动
  • 其他功能按钮:比如菜单按钮、搜索框等

下面就让我们一一部署这些组件吧。

三、标题栏组件实现

1、标题栏基本界面搭建

我们首先创建一个无边框的Qt窗口,在其上绘制标题栏:

复制代码
QWidget *window = new QWidget;
window->setWindowFlags(Qt::FramelessWindowHint); //设置无边框

然后通过样式表设置标题栏的基本外观:

复制代码
#titlebar {
    background-color: #323232;
}

#titlebar QLabel {
    color: white; 
    font-weight: bold;
}

在代码中,我们使用QPushButton、QLabel等Qt控件来创建标题文字、最小化/最大化/关闭按钮:

复制代码
// 标题文字
auto titleLabel = new QLabel(this);
titleLabel->setText("My App");

// 最小化按钮
auto minimizeBtn = new QPushButton(this);
minimizeBtn->setIcon(style->standardIcon(QStyle::SP_TitleBarMinButton));
connect(minimizeBtn, &QPushButton::clicked, this, &CustomTitleBar::showMinimized);

// 其他按钮...

2、实现拖动功能

我们需要在标题栏捕获鼠标的按下、移动、释放事件,根据鼠标的位移来移动整个窗口。

复制代码
// 在mousePressEvent中记录初始位置
m_startPos = event->globalPos();

// 在mouseMoveEvent中根据位移调整窗口位置 
move(geometry().topLeft() + event->globalPos() - m_startPos);

// 在mouseReleaseEvent中重置状态

3、实现双击最大化/恢复

通过重写mouseDoubleClickEvent,当双击标题栏时,我们切换窗口的最大化/恢复状态:

复制代码
void CustomTitleBar::mouseDoubleClickEvent(QMouseEvent *event)
{
    if(window()->isMaximized())
        window()->showNormal();
    else
        window()->showMaximized();
}

四、实战案例

这里给出自定义标题栏的完整源码:

titlebar.h

复制代码
#ifndef TITLEBAR_H
#define TITLEBAR_H

#include <QWidget>
#include <QHBoxLayout>
#include <QLabel>
#include <QPushButton>

class TitleBar : public QWidget
{
    Q_OBJECT

public:
    explicit TitleBar(QWidget *parent = nullptr);

    void setWindowTitle(const QString &title);
    void setWindowIcon(const QIcon &icon);

protected:
    void mousePressEvent(QMouseEvent *event) override;
    void mouseMoveEvent(QMouseEvent *event) override;
    void mouseReleaseEvent(QMouseEvent *event) override;
    void mouseDoubleClickEvent(QMouseEvent *event) override;

private slots:
    void onButtonClicked();

private:
    QLabel *m_titleLabel;
    QPushButton *m_minimizeButton;
    QPushButton *m_maximizeButton;
    QPushButton *m_closeButton;

    QPoint m_startPos;
    bool m_isMousePressed;
};

#endif // TITLEBAR_H

titlebar.cpp:

复制代码
#include "titlebar.h"

#include <QHBoxLayout>
#include <QMouseEvent>
#include <QApplication>
#include <QStyle>

TitleBar::TitleBar(QWidget *parent)
    : QWidget(parent)
    , m_isMousePressed(false)
{
    // 标题文字
    m_titleLabel = new QLabel(this);
    m_titleLabel->setStyleSheet("color: white; font-weight: bold;");

    // 最小化按钮
    m_minimizeButton = new QPushButton(this);
    m_minimizeButton->setIcon(style()->standardIcon(QStyle::SP_TitleBarMinButton));
    connect(m_minimizeButton, &QPushButton::clicked, this, &TitleBar::onButtonClicked);

    // 最大化按钮
    m_maximizeButton = new QPushButton(this);
    m_maximizeButton->setIcon(style()->standardIcon(QStyle::SP_TitleBarMaxButton));
    connect(m_maximizeButton, &QPushButton::clicked, this, &TitleBar::onButtonClicked);

    // 关闭按钮
    m_closeButton = new QPushButton(this);
    m_closeButton->setIcon(style()->standardIcon(QStyle::SP_TitleBarCloseButton));
    connect(m_closeButton, &QPushButton::clicked, this, &TitleBar::onButtonClicked);

    // 布局
    QHBoxLayout *layout = new QHBoxLayout(this);
    layout->addWidget(m_titleLabel);
    layout->addWidget(new QWidget(), 1); // 用于占据中间空间
    layout->addWidget(m_minimizeButton);
    layout->addWidget(m_maximizeButton);
    layout->addWidget(m_closeButton);
    layout->setContentsMargins(5, 5, 5, 5);

    // 设置标题栏样式
    setStyleSheet("background-color: #323232;");
}

void TitleBar::setWindowTitle(const QString &title)
{
    m_titleLabel->setText(title);
}

void TitleBar::setWindowIcon(const QIcon &icon)
{
    m_titleLabel->setPixmap(icon.pixmap(16, 16));
}

void TitleBar::mousePressEvent(QMouseEvent *event)
{
    if (event->button() == Qt::LeftButton) {
        m_isMousePressed = true;
        m_startPos = event->globalPos();
    }
}

void TitleBar::mouseMoveEvent(QMouseEvent *event)
{
    if (m_isMousePressed) {
        QPoint delta = event->globalPos() - m_startPos;
        window()->move(window()->pos() + delta);
    }
}

void TitleBar::mouseReleaseEvent(QMouseEvent *event)
{
    if (event->button() == Qt::LeftButton) {
        m_isMousePressed = false;
    }
}

void TitleBar::mouseDoubleClickEvent(QMouseEvent *event)
{
    Q_UNUSED(event)
    if (window()->isMaximized()) {
        window()->showNormal();
    } else {
        window()->showMaximized();
    }
}

void TitleBar::onButtonClicked()
{
    QPushButton *button = qobject_cast<QPushButton *>(sender());
    QWidget *window = this->window();

    if (button == m_minimizeButton) {
        window->showMinimized();
    } else if (button == m_maximizeButton) {
        if (window->isMaximized()) {
            window->showNormal();
        } else {
            window->showMaximized();
        }
    } else if (button == m_closeButton) {
        window->close();
    }
}

在主窗口中使用自定义标题栏:

复制代码
#include "titlebar.h"
#include <QVBoxLayout>

int main(int argc, char *argv[])
{
    QApplication app(argc, argv);

    QWidget window;
    window.setWindowFlags(Qt::FramelessWindowHint); // 设置无边框

    TitleBar *titleBar = new TitleBar(&window);
    titleBar->setWindowTitle("My Application");
    titleBar->setWindowIcon(QIcon(":/icons/app.ico"));

    QWidget *centralWidget = new QWidget;
    // 添加你的主界面组件...

    QVBoxLayout *layout = new QVBoxLayout(&window);
    layout->addWidget(titleBar);
    layout->addWidget(centralWidget);

    window.show();
    return app.exec();
}

以上代码实现了一个基本的自定义标题栏,包括标题文字、最小化/最大化/关闭按钮、窗口拖动等功能。您可以根据需求对代码进行修改和扩展,比如添加更多自定义按钮、集成QSS样式等。

结语

通过本文的实战演练,我们成功实现了一个基本的自定义标题栏。当然,这只是一个起点,你可以根据需求进一步扩展和优化,比如添加透明度调节、自定义按钮等。

相关推荐
哞哞不熬夜3 分钟前
JavaEE--SpringIoC
java·开发语言·spring boot·spring·java-ee·maven
newxtc7 分钟前
【猿辅导-注册安全分析报告-无验证方式导致安全隐患】
开发语言·selenium·安全·yolo·安全爆破
张人玉9 分钟前
c#WPF基础知识
开发语言·c#·wpf
std78791 小时前
Rust 与 Go – 比较以及每个如何满足您的需求
开发语言·golang·rust
报错小能手1 小时前
python(入门)map内置函数及import模块导入,as别名
开发语言·人工智能·python
梵得儿SHI1 小时前
Java 反射机制实战:对象属性复制与私有方法调用全解析
java·开发语言·java反射机制的实际应用·对象属性复制·反射调用私有方法·私有字段·类型兼容性和敏感字段忽略
sulikey1 小时前
C++的STL:深入理解 C++ 的 std::initializer_list
开发语言·c++·stl·list·initializerlist·c++标准库
liu****1 小时前
19.map和set的封装
开发语言·数据结构·c++·算法
孤廖1 小时前
C++ 模板再升级:非类型参数、特化技巧(含全特化与偏特化)、分离编译破解
linux·服务器·开发语言·c++·人工智能·后端·深度学习
润 下1 小时前
C语言——回调函数的典型示例(分析详解)
c语言·开发语言·人工智能·经验分享·笔记·程序人生