Qt 自定义窗口的标题栏,重写鼠标事件实现,隐藏窗口,最大化/最小化窗口,关闭窗口
1、main.cpp
#include "widget.h"
#include <QApplication>
int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    Widget w;
    w.show();
    return a.exec();
}
2、widget.h
#ifndef WIDGET_H
#define WIDGET_H
#include <QWidget>
QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACE
class Widget : public QWidget
{
    Q_OBJECT
public:
    Widget(QWidget *parent = nullptr);
    ~Widget();
private:
    Ui::Widget *ui;
protected:
    // 重写鼠标事件,实现(隐藏窗口,最大化/最小化窗口,关闭窗口)
    void mousePressEvent(QMouseEvent *event) override; // 重写鼠标按下事件
    void mouseMoveEvent(QMouseEvent *event) override; // 重写鼠标移动事件
    void mouseReleaseEvent(QMouseEvent *event) override; // 重写鼠标释放事件
    /* 1、将函数声明为virtual的作用是允许这两个函数在派生类中被重写(override),
     * 因为resizeEvent()和moveEvent()是QWidget类中的虚函数,因此在派生类中也要将其声明为virtual,
     * 这样就可以在派生类中重新定义这两个函数,以实现派生类中对窗口大小改变和窗口移动事件的处理
     */
    virtual void resizeEvent(QResizeEvent *event);
    virtual void moveEvent(QMoveEvent *event);
private:
    QWidget *content;       // 中央控件
    QWidget *titleBar;      // 自定义标题栏
    bool isPressed;         // 是否按下鼠标左键
    QPoint mousePos;        // 鼠标按下时相对于窗口左上角的位置
// 声明标题栏槽函数(隐藏窗口,最大化/最小化窗口,关闭窗口)
private slots:
    void on_tbn_min_clicked();
    void on_tbn_max_clicked();
    void on_tbn_close_clicked();
};
#endif // WIDGET_H
3、widget.cpp
#include "widget.h"
#include "ui_widget.h"
#include <QMouseEvent> // 1、包含QMouseEvent类的头文件
#include <QHBoxLayout>
#include <QLabel>
#include <QPushButton>
Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);
    // 2、去除默认的标题栏和边框
    // Qt::FramelessWindowHint:这是一个窗口提示,表示窗口没有边框
    // Qt::WindowMinimizeButtonHint:这是一个窗口提示,表示窗口有最小化按钮
    // Qt::WindowMaximizeButtonHint:这是一个窗口提示,表示窗口有最大化按钮
    // Qt::WindowCloseButtonHint:这是一个窗口提示,表示窗口有关闭按钮
    this->setWindowFlags(Qt::FramelessWindowHint | Qt::WindowMinimizeButtonHint | Qt::WindowMaximizeButtonHint | Qt::WindowCloseButtonHint);
    // 创建content容器,放到Widget窗口上
    content = new QWidget(this);
    // 设置 objectName 属性,QSS 文件中使用 #objectName 来定位到该控件
    content->setObjectName("content");
    // 设置content的大小策略,就是当窗口大小变化时,content怎么调整自己的大小,第一个参数是水平方向上的策略,第二个参数是垂直方向上的策略
    content->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
    // 设置content的位置和大小,参数是x坐标、y坐标、宽度和高度
    content->setGeometry(0, 0, width(), height());
    content->setStyleSheet("background-color:red;");
    // 在content上创建一个垂直布局,下面的2种方法都可以
    // content->setLayout(contentVLayout);
    QVBoxLayout *contentVLayout = new QVBoxLayout(content);
    // 3、自定义标题栏(隐藏窗口,最大化/最小化窗口,关闭窗口)
    // 创建titleBar容器,放到content容器里
    // titleBar = new QWidget(content);
    titleBar = new QWidget();
    titleBar->setObjectName("titleBar");
    titleBar->setStyleSheet("background-color:blue;");
    // 把titleBar添加到contentVLayout布局中
    contentVLayout->addWidget(titleBar);
    // 设置对齐方式为顶部对齐,让titleBar显示在垂直布局中的最上面
    contentVLayout->setAlignment(titleBar, Qt::AlignTop);
    // 设置内容边距为0,让它的子部件紧贴着它的边缘
    // 给contentVLayout这个垂直布局设置内边距为0,内边距是指布局和它的子部件之间的空隙
    // setContentsMargins()方法4个参数,分别表示左边距,上边距,右边距和下边距
    contentVLayout->setContentsMargins(0, 0, 0, 0);
    // 水平方向上可以自动扩展,在垂直方向上保持固定大小
    titleBar->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
    // 设置标题栏控件的位置和大小
    titleBar->setGeometry(0, 0, width(), 60);
    // 在titleBar上创建一个水平布局
    QHBoxLayout *titleBarHLayout = new QHBoxLayout(titleBar);
    // Qt::AlignLeft    水平方向靠左
    // Qt::AlignRight   水平方向靠右
    // Qt::AlignHCenter 水平方向居中
    // Qt::AlignTop     垂直方向靠上
    titleBarHLayout->setAlignment(Qt::AlignHCenter);
    // 在titleBarHLayout上添加你想要的控件,比如图标、标题、最小化按钮、最大化按钮、关闭按钮等
    QLabel *iconLabel = new QLabel(titleBar); // 创建图标标签
    iconLabel->setPixmap(QPixmap(":/imagenns/icon.png")); // 设置图标标签的图片
    iconLabel->setScaledContents(true); // 设置图标标签的图片自动缩放
    iconLabel->setFixedSize(20, 20); // 设置图标标签的固定大小
    QLabel *titleLabel = new QLabel(titleBar); // 创建标题标签
    titleLabel->setText("QWidget布局"); // 设置标题标签的文本
    titleLabel->setFont(QFont("Arial", 12, QFont::Bold)); // 设置标题标签的字体
    QPushButton *minButton = new QPushButton(titleBar); // 创建最小化按钮
    minButton->setText("-"); // 设置最小化按钮的文本
    minButton->setFixedSize(20, 20); // 设置最小化按钮的固定大小
    QPushButton *maxButton = new QPushButton(titleBar); // 创建最大化按钮
    maxButton->setText("+"); // 设置最大化按钮的文本
    maxButton->setFixedSize(20, 20); // 设置最大化按钮的固定大小
    QPushButton *closeButton = new QPushButton(titleBar); // 创建关闭按钮
    closeButton->setText("x"); // 设置关闭按钮的文本
    closeButton->setFixedSize(20, 20); // 设置关闭按钮的固定大小
    // 将这些控件添加到水平布局中,并设置合适的间距和弹簧
    titleBarHLayout->addWidget(iconLabel); // 将图标标签添加到水平布局中
    titleBarHLayout->addSpacing(10); // 添加10像素的间距
    titleBarHLayout->addWidget(titleLabel); // 将标题标签添加到水平布局中
    titleBarHLayout->addStretch(); // 添加弹簧,使得后面的按钮靠右对齐
    titleBarHLayout->addWidget(minButton); // 将最小化按钮添加到水平布局中
    titleBarHLayout->addWidget(maxButton); // 将最大化按钮添加到水平布局中
    titleBarHLayout->addWidget(closeButton); // 将关闭按钮添加到水平布局中
    connect (minButton, SIGNAL (clicked ()), this, SLOT (on_tbn_min_clicked ())); // 连接最小化按钮的信号和槽
    connect (maxButton, SIGNAL (clicked ()), this, SLOT (on_tbn_max_clicked ())); // 连接最大化按钮的信号和槽
    connect (closeButton, SIGNAL (clicked ()), this, SLOT (on_tbn_close_clicked ())); // 连接关闭按钮的信号和槽
}
Widget::~Widget()
{
    delete ui;
}
// 最小化按钮的槽函数
void Widget::on_tbn_min_clicked()
{
    // 最小化窗口
    showMinimized();
}
// 最大化按钮的槽函数
void Widget::on_tbn_max_clicked()
{
   if (isMaximized()) {
        // 还原窗口
        showNormal();
        // 切换图标
        qobject_cast<QPushButton *>(sender())->setText("+"); // 使用qobject_cast转换类型,并修改文本
   } else {
        // 最大化窗口
        showMaximized();
        qobject_cast<QPushButton *>(sender())->setText("-");
   }
}
// 关闭按钮的槽函数
void Widget::on_tbn_close_clicked()
{
   close();
}
// 重写鼠标事件,实现(隐藏窗口,最大化/最小化窗口,关闭窗口)
// 重写鼠标按下事件
void Widget::mousePressEvent(QMouseEvent *event)
{
    if (event->button() == Qt::LeftButton) { // 如果是鼠标左键按下
        isPressed = true; // 标记为按下状态
        mousePos = event->pos(); // 记录鼠标相对于窗口左上角的位置
    }
}
// 重写鼠标移动事件
void Widget::mouseMoveEvent(QMouseEvent *event)
{
    if (isPressed) { // 如果是按下状态
        move(event->globalPos() - mousePos); // 移动窗口到鼠标当前位置减去鼠标相对于窗口左上角位置之差处
    }
}
// 重写鼠标释放事件
void Widget::mouseReleaseEvent(QMouseEvent *event)
{
    if (event->button() == Qt::LeftButton) { // 如果是鼠标左键释放
        isPressed = false; // 标记为非按下状态
    }
}
/* 如果要实现widget窗口跟随鼠标拖动并自动跟随窗口缩放,
 * 需要在QWidget类中重写resizeEvent()函数和moveEvent()函数
 */
// 在resizeEvent()函数中,重新设置widget窗口的大小和位置
void Widget::resizeEvent(QResizeEvent *event)
{
    QWidget::resizeEvent(event); // 调用父类的resizeEvent()函数
    if(this->content) // 判断是否有widget被添加到Material窗口中
    {
        // 获取Material窗口的大小
        int w = this->width();
        int h = this->height();
        // 设置widget的大小为Material窗口的大小
        this->content->setGeometry(0, 0, w, h);
    }
}
// 在moveEvent()函数中,重新设置widget窗口的位置
void Widget::moveEvent(QMoveEvent *event)
{
    QWidget::moveEvent(event);
    if(this->content)
    {
        this->content->move(0, 0);
    }
}
4、效果展示
 
5、完成













![[高光谱]高光谱数据的获取与展示](https://img-blog.csdnimg.cn/7f59c3b79a47411393770418d304a1ff.png)





