【问题标题】:Making a borderless window with for Qt使用 for Qt 制作无边框窗口
【发布时间】:2011-01-15 04:12:24
【问题描述】:

我是 Qt C++ 的新手。我下载了最新的 windows 版本,做了一些教程,非常棒。

我看到了 Qt 框架具有的一些样式选项,并且非常棒,但现在我需要构建我的应用程序,它的主窗口(窗体)用没有矩形边框(无边框?)的图像设计/蒙皮。

我怎样才能用 Qt 做到这一点?

【问题讨论】:

    标签: c++ qt themes styling


    【解决方案1】:

    如果您正在寻找一些小部件形状的高级样式,也许这个示例会对您有所帮助:

    Shaped Clock Example

    或者您可能只是在寻找这种标志:Qt::CustomizeWindowHint 或只是 Qt::FramelessWindowHint

    【讨论】:

    • 异形时钟的例子就是这样,还有像这样的例子吗?
    • 代码如下:Qt::WindowFlags flags = this->windowFlags(); this->setWindowFlags(flags|Qt::FramelessWindowHint);
    【解决方案2】:

    我创建了一个小例子,说明如何在 Qt5 中创建类似 VS2013 的无框窗口:

    您可以在这里获得完整的来源:https://github.com/Jorgen-VikingGod/Qt-Frameless-Window-DarkStyle

    否则这里是如何将“主”主窗口嵌入“无框架”窗口的代码概述。您还可以了解如何添加标题栏、按钮以及如何最大化、调整和移动无框窗口。

    主窗口.h

    #ifndef MAINWINDOW_H
    #define MAINWINDOW_H
    
    #include <QtWidgets>
    
    /*
    place your QMainWindow code here
    */
    namespace Ui {
      class MainWindow;
    }
    
    class MainWindow : public QMainWindow
    {
      Q_OBJECT
    public:
      explicit MainWindow(QWidget *parent = 0);
      ~MainWindow();
    private:
      Ui::MainWindow *ui;
    };
    
    /*
    this class is to add frameless window supoort and do all the stuff with titlebar and buttons
    */
    class BorderlessMainWindow: public QMainWindow
    {
      Q_OBJECT
    public:
      explicit BorderlessMainWindow(QWidget *parent = 0);
      ~BorderlessMainWindow() {}
    protected:
      void mouseMoveEvent(QMouseEvent* event);
      void mousePressEvent(QMouseEvent* event);
      void mouseReleaseEvent(QMouseEvent* event);
      void mouseDoubleClickEvent(QMouseEvent *event);
    private slots:
      void slot_minimized();
      void slot_restored();
      void slot_maximized();
      void slot_closed();
    private:
      MainWindow *mMainWindow;
      QWidget *mTitlebarWidget;
      QLabel *mWindowTitle;
      QPushButton *mMinimizeButton;
      QPushButton *mRestoreButton;
      QPushButton *mMaximizeButton;
      QPushButton *mCloseButton;
      QPoint mLastMousePosition;
      bool mMoving;
      bool mMaximized;
    };
    
    #endif // MAINWINDOW_H
    

    主窗口.cpp

    #include "mainwindow.h"
    #include "ui_mainwindow.h"
    #include <QDebug>
    
    /*
    frameless window class: it adds the MainWindow class inside the centralWidget
    */
    BorderlessMainWindow::BorderlessMainWindow(QWidget *parent) : QMainWindow(parent, Qt::CustomizeWindowHint ) {
      setObjectName("borderlessMainWindow");
      setWindowFlags(Qt::FramelessWindowHint| Qt::WindowSystemMenuHint);
      // to fix taskbar minimize feature
      setWindowFlags(windowFlags() | Qt::WindowMinimizeButtonHint);
    
      mMainWindow = new MainWindow(this);
      setWindowTitle(mMainWindow->windowTitle());
    
      QVBoxLayout *verticalLayout = new QVBoxLayout();
      verticalLayout->setSpacing(0);
      verticalLayout->setMargin(1);
    
      QHBoxLayout *horizontalLayout = new QHBoxLayout();
      horizontalLayout->setSpacing(0);
      horizontalLayout->setMargin(0);
    
      mTitlebarWidget = new QWidget(this);
      mTitlebarWidget->setObjectName("titlebarWidget");
      mTitlebarWidget->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred);
      mTitlebarWidget->setLayout(horizontalLayout);
    
      mMinimizeButton = new QPushButton(mTitlebarWidget);
      mMinimizeButton->setObjectName("minimizeButton");
      connect(mMinimizeButton, SIGNAL(clicked()), this, SLOT(slot_minimized()));
    
      mRestoreButton = new QPushButton(mTitlebarWidget);
      mRestoreButton->setObjectName("restoreButton");
      mRestoreButton->setVisible(false);
      connect(mRestoreButton, SIGNAL(clicked()), this, SLOT(slot_restored()));
    
      mMaximizeButton = new QPushButton(mTitlebarWidget);
      mMaximizeButton->setObjectName("maximizeButton");
      connect(mMaximizeButton, SIGNAL(clicked()), this, SLOT(slot_maximized()));
    
      mCloseButton = new QPushButton(mTitlebarWidget);
      mCloseButton->setObjectName("closeButton");
      connect(mCloseButton, SIGNAL(clicked()), this, SLOT(slot_closed()));
    
      mWindowTitle = new QLabel(mTitlebarWidget);
      mWindowTitle->setObjectName("windowTitle");
      mWindowTitle->setText(windowTitle());
    
      horizontalLayout->addWidget(mWindowTitle);
      horizontalLayout->addStretch(1);
      horizontalLayout->addWidget(mMinimizeButton);
      horizontalLayout->addWidget(mRestoreButton);
      horizontalLayout->addWidget(mMaximizeButton);
      horizontalLayout->addWidget(mCloseButton);
    
      verticalLayout->addWidget(mTitlebarWidget);
      verticalLayout->addWidget(mMainWindow);
    
      QWidget *centralWidget = new QWidget(this);
      centralWidget->setObjectName("centralWidget");
      centralWidget->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
      centralWidget->setLayout(verticalLayout);
    
      setCentralWidget(centralWidget);
    }
    void BorderlessMainWindow::mousePressEvent(QMouseEvent* event) {
      if (!mTitlebarWidget->underMouse() && !mWindowTitle->underMouse())
        return;
    
      if(event->button() == Qt::LeftButton) {
        mMoving = true;
        mLastMousePosition = event->pos();
      }
    }
    void BorderlessMainWindow::mouseMoveEvent(QMouseEvent* event) {
      if (!mTitlebarWidget->underMouse() && !mWindowTitle->underMouse())
        return;
    
      if( event->buttons().testFlag(Qt::LeftButton) && mMoving) {
        this->move(this->pos() + (event->pos() - mLastMousePosition));
      }
    }
    void BorderlessMainWindow::mouseReleaseEvent(QMouseEvent* event) {
      if (!mTitlebarWidget->underMouse() && !mWindowTitle->underMouse())
        return;
    
      if(event->button() == Qt::LeftButton) {
        mMoving = false;
      }
    }
    void BorderlessMainWindow::mouseDoubleClickEvent(QMouseEvent *event) {
      Q_UNUSED(event);
      if (!mTitlebarWidget->underMouse() && !mWindowTitle->underMouse())
        return;
    
      mMaximized = !mMaximized;
      if (mMaximized) {
        slot_maximized();
      } else {
        slot_restored();
      }
    }
    void BorderlessMainWindow::slot_minimized() {
      setWindowState(Qt::WindowMinimized);
    }
    void BorderlessMainWindow::slot_restored() {
      mRestoreButton->setVisible(false);
      mMaximizeButton->setVisible(true);
      setWindowState(Qt::WindowNoState);
      setStyleSheet("#borderlessMainWindow{border:1px solid palette(highlight);}");
    }
    void BorderlessMainWindow::slot_maximized() {
      mRestoreButton->setVisible(true);
      mMaximizeButton->setVisible(false);
      setWindowState(Qt::WindowMaximized);
      setStyleSheet("#borderlessMainWindow{border:1px solid palette(base);}");
    }
    void BorderlessMainWindow::slot_closed() {
      close();
    }
    
    /*
    MainWindow class: put all your code here
    */
    MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent, Qt::FramelessWindowHint), ui(new Ui::MainWindow) {
      ui->setupUi(this);
      statusBar()->setSizeGripEnabled(true);
    }
    
    MainWindow::~MainWindow() {
      delete ui;
    }
    

    【讨论】:

    • 虽然此链接可能会回答问题,但最好在此处包含答案的基本部分并提供链接以供参考。如果链接页面发生更改,仅链接答案可能会失效。请阅读此how-to-answer 以提供高质量的答案。
    【解决方案3】:

    在您的 Qt 目录中有一个示例应用程序:examples/widgets/windowsflags

    【讨论】:

      【解决方案4】:

      我自己遇到了这个问题,过了一段时间才弄清楚。查看https://github.com/ianbannerman/TrueFramelessWindow 以获取适用于 Windows 和 macOS 的示例代码。

      Qt::FramelessWindowHint 牺牲了调整大小和最小/最大/关闭,所以可能不是大多数人想要的。

      【讨论】:

      • 读者注意:您仍然可以自己处理最小/最大/关闭/调整大小/拖动操作。它需要额外的代码,但这是可能的。我有一个不错的无框应用程序,它带有我自己的自定义标题栏,它的作用就像一个真实的窗口。
      • @JohnDoe 您的代码是否也可以在 linux 上运行?抱歉在这里问,但我开始变得绝望;)
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-02-15
      • 1970-01-01
      • 2014-03-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多