QT无边框窗口

发布于:2025-07-21 ⋅ 阅读:(12) ⋅ 点赞:(0)

1. 创建无边框窗口

通过设置窗口标志来去掉边框。

#include <QtWidgets/QMainWindow>
#include <QtWidgets/QWidget>
#include <QtCore/Qt>

class MainWindow : public QMainWindow {
public:
    MainWindow() {
        // 去掉边框
        setWindowFlags(Qt::FramelessWindowHint);
        // 设置窗口大小
        resize(800, 600);
    }
};

2. 创建自定义标题栏

创建一个继承自 QWidget 的类,包含按钮和标题。

#include <QtWidgets/QWidget>
#include <QtWidgets/QPushButton>
#include <QtWidgets/QHBoxLayout>
#include <QtWidgets/QLabel>
#include <QtCore/Qt>

class CustomTitleBar : public QWidget {
public:
    CustomTitleBar(QWidget* parent = nullptr) : QWidget(parent) {
        setupUI();
    }

private:
    void setupUI() {
        QHBoxLayout* layout = new QHBoxLayout(this);
        layout->setContentsMargins(0, 0, 0, 0);

        // 标题
        QLabel* title = new QLabel(parent()->windowTitle());
        layout->addWidget(title);

        // 按钮
        QPushButton* minBtn = new QPushButton("最小化");
        QPushButton* maxBtn = new QPushButton("最大化");
        QPushButton* closeBtn = new QPushButton("关闭");

        layout->addWidget(minBtn);
        layout->addWidget(maxBtn);
        layout->addWidget(closeBtn);

        // 信号连接
        connect(minBtn, &QPushButton::clicked, parent(), &QWidget::showMinimized);
        connect(maxBtn, &QPushButton::clicked, parent(), &QWidget::showMaximized);
        connect(closeBtn, &QPushButton::clicked, parent(), &QWidget::close);
    }
};

3. 处理窗口移动

重写鼠标事件,实现拖动窗口。

#include <QtWidgets/QMainWindow>
#include <QtCore/QPoint>
#include <QtCore/QMouseEvent>

class MainWindow : public QMainWindow {
public:
    MainWindow() {
        setWindowFlags(Qt::FramelessWindowHint);
        resize(800, 600);

        // 添加自定义标题栏
        CustomTitleBar* titleBar = new CustomTitleBar(this);
        setMenuWidget(titleBar); // 将标题栏设置为菜单栏
    }

protected:
    bool dragging = false;
    QPoint dragPos;

    void mousePressEvent(QMouseEvent* event) override {
        if (event->button() == Qt::LeftButton) {
            dragging = true;
            dragPos = event->globalPos() - pos();
            event->accept();
        }
    }

    void mouseMoveEvent(QMouseEvent* event) override {
        if (dragging) {
            move(event->globalPos() - dragPos);
            event->accept();
        }
    }

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

4. 处理窗口调整大小

重写调整大小事件,确保标题栏正确显示。

#include <QtWidgets/QMainWindow>
#include <QtWidgets/QWidget>
#include <QtCore/QEvent>

class MainWindow : public QMainWindow {
public:
    MainWindow() {
        setWindowFlags(Qt::FramelessWindowHint);
        resize(800, 600);

        CustomTitleBar* titleBar = new CustomTitleBar(this);
        setMenuWidget(titleBar);
    }

protected:
    void resizeEvent(QResizeEvent* event) override {
        QMainWindow::resizeEvent(event);

        // 确保标题栏的大小与窗口一致
        if (menuWidget()) {
            menuWidget()->setGeometry(QRect(0, 0, width(), menuWidget()->height()));
        }
    }
};

5. 复用标题栏

将标题栏类作为独立组件,多个窗口可复用。

#include <QtWidgets/QMainWindow>
#include <QtWidgets/QWidget>
#include <QtCore/Qt>

class AnotherWindow : public QMainWindow {
public:
    AnotherWindow() {
        setWindowFlags(Qt::FramelessWindowHint);
        resize(400, 300);

        CustomTitleBar* titleBar = new CustomTitleBar(this);
        setMenuWidget(titleBar);
    }

protected:
    bool dragging = false;
    QPoint dragPos;

    void mousePressEvent(QMouseEvent* event) override {
        if (event->button() == Qt::LeftButton) {
            dragging = true;
            dragPos = event->globalPos() - pos();
            event->accept();
        }
    }

    void mouseMoveEvent(QMouseEvent* event) override {
        if (dragging) {
            move(event->globalPos() - dragPos);
            event->accept();
        }
    }

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

    void resizeEvent(QResizeEvent* event) override {
        QMainWindow::resizeEvent(event);

        if (menuWidget()) {
            menuWidget()->setGeometry(QRect(0, 0, width(), menuWidget()->height()));
        }
    }
};

6. 完整示例代码

#include <QtWidgets/QApplication>
#include <QtWidgets/QMainWindow>
#include <QtWidgets/QWidget>
#include <QtWidgets/QPushButton>
#include <QtWidgets/QHBoxLayout>
#include <QtWidgets/QLabel>
#include <QtCore/Qt>
#include <QtCore/QPoint>
#include <QtCore/QMouseEvent>
#include <QtCore/QResizeEvent>

// 自定义标题栏类
class CustomTitleBar : public QWidget {
public:
    CustomTitleBar(QWidget* parent = nullptr) : QWidget(parent) {
        setupUI();
    }

private:
    void setupUI() {
        QHBoxLayout* layout = new QHBoxLayout(this);
        layout->setContentsMargins(0, 0, 0, 0);

        QLabel* title = new QLabel(parent()->windowTitle());
        layout->addWidget(title);

        QPushButton* minBtn = new QPushButton("最小化");
        QPushButton* maxBtn = new QPushButton("最大化");
        QPushButton* closeBtn = new QPushButton("关闭");

        layout->addWidget(minBtn);
        layout->addWidget(maxBtn);
        layout->addWidget(closeBtn);

        connect(minBtn, &QPushButton::clicked, parent(), &QWidget::showMinimized);
        connect(maxBtn, &QPushButton::clicked, parent(), &QWidget::showMaximized);
        connect(closeBtn, &QPushButton::clicked, parent(), &QWidget::close);
    }
};

// 主窗口类
class MainWindow : public QMainWindow {
public:
    MainWindow() {
        setWindowFlags(Qt::FramelessWindowHint);
        resize(800, 600);

        CustomTitleBar* titleBar = new CustomTitleBar(this);
        setMenuWidget(titleBar);
    }

protected:
    bool dragging = false;
    QPoint dragPos;

    void mousePressEvent(QMouseEvent* event) override {
        if (event->button() == Qt::LeftButton) {
            dragging = true;
            dragPos = event->globalPos() - pos();
            event->accept();
        }
    }

    void mouseMoveEvent(QMouseEvent* event) override {
        if (dragging) {
            move(event->globalPos() - dragPos);
            event->accept();
        }
    }

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

    void resizeEvent(QResizeEvent* event) override {
        QMainWindow::resizeEvent(event);

        if (menuWidget()) {
            menuWidget()->setGeometry(QRect(0, 0, width(), menuWidget()->height()));
        }
    }
};

// 另一个窗口类
class AnotherWindow : public QMainWindow {
public:
    AnotherWindow() {
        setWindowFlags(Qt::FramelessWindowHint);
        resize(400, 300);

        CustomTitleBar* titleBar = new CustomTitleBar(this);
        setMenuWidget(titleBar);
    }

protected:
    bool dragging = false;
    QPoint dragPos;

    void mousePressEvent(QMouseEvent* event) override {
        if (event->button() == Qt::LeftButton) {
            dragging = true;
            dragPos = event->globalPos() - pos();
            event->accept();
        }
    }

    void mouseMoveEvent(QMouseEvent* event) override {
        if (dragging) {
            move(event->globalPos() - dragPos);
            event->accept();
        }
    }

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

    void resizeEvent(QResizeEvent* event) override {
        QMainWindow::resizeEvent(event);

        if (menuWidget()) {
            menuWidget()->setGeometry(QRect(0, 0, width(), menuWidget()->height()));
        }
    }
};

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

    MainWindow mainWindow;
    AnotherWindow anotherWindow;

    mainWindow.show();
    anotherWindow.show();

    return app.exec();
}

7. 功能说明

无边框窗口:通过 setWindowFlags(Qt::FramelessWindowHint) 实现。

  • 自定义标题栏:创建 CustomTitleBar 类,包含标题和按钮。
  • 窗口移动:重写鼠标事件 (mousePressEvent, mouseMoveEvent, mouseReleaseEvent) 实现拖动窗口。
  • 窗口调整大小:重写 resizeEvent,确保标题栏正确显示。
  • 复用标题栏:CustomTitleBar 作为独立组件,多个窗口可复用。

网站公告

今日签到

点亮在社区的每一天
去签到