使用 for Qt 制作无边框窗口

Posted

技术标签:

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

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

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

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

【问题讨论】:

【参考方案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("#borderlessMainWindowborder:1px solid palette(highlight);");

void BorderlessMainWindow::slot_maximized() 
  mRestoreButton->setVisible(true);
  mMaximizeButton->setVisible(false);
  setWindowState(Qt::WindowMaximized);
  setStyleSheet("#borderlessMainWindowborder: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 上运行?抱歉在这里问,但我开始变得绝望;)

以上是关于使用 for Qt 制作无边框窗口的主要内容,如果未能解决你的问题,请参考以下文章

在 Qt 中使用无边框窗口的 Aero Snap

QT窗口缩放,自定义边框,无边框缩放拉伸

QT窗口无边框最前

Qt商业级无边框窗口实现源码(windowsmsvc)

VC MFC中如何制作无边框窗口

QT_无边框窗口拖动缩放