窗口标志示例
“窗口标志”示例演示了如何使用 Qt 中提供的窗口标志。
窗口标志可以是类型,也可以是提示。类型用于为小部件指定各种窗口系统属性。一个小部件只能有一个类型,默认类型为Qt::Widget 。但是,一个小部件可以有零个或多个提示。这些提示用于自定义顶级窗口的外观。
小部件的标志存储在Qt::WindowFlags 类型中,该类型存储了标志的或(OR)组合。

“窗口标志”示例的屏幕截图
该示例由两个类组成:
ControllerWindow是主应用程序控件,允许用户从可用的窗口标志中进行选择,并在单独的预览窗口中显示效果。PreviewWindow是一个自定义控件,用于在只读文本编辑器中显示当前设置的窗口标志名称。
我们将首先回顾ControllerWindow 类,然后了解PreviewWindow 类。
ControllerWindow 类定义
class ControllerWindow : public QWidget
{
Q_OBJECT
public:
ControllerWindow(QWidget *parent = nullptr);
private slots:
void updatePreview();
private:
void createTypeGroupBox();
void createHintsGroupBox();
QCheckBox *createCheckBox(const QString &text);
QRadioButton *createRadioButton(const QString &text);
PreviewWindow *previewWindow;
QGroupBox *typeGroupBox;
QGroupBox *hintsGroupBox;
QPushButton *quitButton;
QRadioButton *windowRadioButton;
QRadioButton *dialogRadioButton;
QRadioButton *sheetRadioButton;
QRadioButton *drawerRadioButton;
QRadioButton *popupRadioButton;
QRadioButton *toolRadioButton;
QRadioButton *toolTipRadioButton;
QRadioButton *splashScreenRadioButton;
QCheckBox *msWindowsFixedSizeDialogCheckBox;
QCheckBox *x11BypassWindowManagerCheckBox;
QCheckBox *framelessWindowCheckBox;
QCheckBox *windowNoShadowCheckBox;
QCheckBox *windowTitleCheckBox;
QCheckBox *windowSystemMenuCheckBox;
QCheckBox *windowMinimizeButtonCheckBox;
QCheckBox *windowMaximizeButtonCheckBox;
QCheckBox *windowCloseButtonCheckBox;
QCheckBox *windowContextHelpButtonCheckBox;
QCheckBox *windowShadeButtonCheckBox;
QCheckBox *windowStaysOnTopCheckBox;
QCheckBox *windowStaysOnBottomCheckBox;
QCheckBox *customizeWindowHintCheckBox;
};ControllerWindow 类继承自QWidget 类。该控件允许用户从可用的窗口标志中进行选择,并在单独的预览窗口中显示效果。
我们声明了一个私有的updatePreview() 槽,以便在用户更改窗口标志时刷新预览窗口。
我们还声明了几个私有函数以简化构造函数:我们调用createTypeGroupBox() 函数,利用私有函数createButton() 为每种可用的窗口类型创建一个单选按钮,并将它们收集到一个组框中。同样地,我们使用createHintsGroupBox() 函数,利用私有函数createCheckBox() 为每个可用的提示创建一个复选框。
除了各种单选按钮和复选框外,我们还需要一个关联的PreviewWindow ,用于显示当前所选窗口标志的效果。

ControllerWindow 类的实现
ControllerWindow::ControllerWindow(QWidget*parent)
: QWidget(parent)
{
previewWindow= newPreviewWindow(this);
createTypeGroupBox();
createHintsGroupBox();
quitButton= newQPushButton(tr("&退出"));
connect(quitButton, &QPushButton::clicked,
qApp, &QCoreApplication::quit);
QHBoxLayout*bottomLayout = newQHBoxLayout;
bottomLayout->addStretch();
bottomLayout->addWidget(quitButton);
QHBoxLayout*mainLayout = newQHBoxLayout;
mainLayout->addWidget(typeGroupBox);
mainLayout->addWidget(hintsGroupBox);
mainLayout->addLayout(bottomLayout);
setLayout(mainLayout);
setWindowTitle(tr("Window Flags"));
updatePreview();
}在构造函数中,我们首先创建预览窗口。然后,利用私有函数createTypeGroupBox() 和createHintsGroupBox() 创建包含可用窗口标志的组框。此外,我们还创建了一个Quit 按钮。我们将该按钮和一个可伸缩区域放置在单独的布局中,以使按钮显示在WindowFlag 控件的右下角。
最后,我们将按钮的布局和两个组框添加到QVBoxLayout 中,设置窗口标题,并通过updatePreview() 槽刷新预览窗口。
void ControllerWindow::updatePreview()
{
Qt::WindowFlags flags;
if (windowRadioButton->isChecked())
flags = Qt::Window;
else if (dialogRadioButton->isChecked())
flags = Qt::Dialog;
else if (sheetRadioButton->isChecked())
flags = Qt::Sheet;
else if (drawerRadioButton->isChecked())
flags = Qt::Drawer;
else if (popupRadioButton->isChecked())
flags = Qt::Popup;
else if (toolRadioButton->isChecked())
flags = Qt::Tool;
else if (toolTipRadioButton->isChecked())
flags = Qt::ToolTip;
else if (splashScreenRadioButton->isChecked())
flags = Qt::SplashScreen;每当用户更改任何窗口标志时,都会调用updatePreview() 槽。首先,我们创建一个空的Qt::WindowFlags flags ,然后确定哪些类型被选中,并将它们添加到flags 中。
if (msWindowsFixedSizeDialogCheckBox->isChecked())
flags |= Qt::MSWindowsFixedSizeDialogHint;
if (x11BypassWindowManagerCheckBox->isChecked())
flags |= Qt::X11BypassWindowManagerHint;
if (framelessWindowCheckBox->isChecked())
flags |= Qt::FramelessWindowHint;
if (windowNoShadowCheckBox->isChecked())
flags |= Qt::NoDropShadowWindowHint;
if (windowTitleCheckBox->isChecked())
flags |= Qt::WindowTitleHint;
if (windowSystemMenuCheckBox->isChecked())
flags |= Qt::WindowSystemMenuHint;
if (windowMinimizeButtonCheckBox->isChecked())
flags |= Qt::WindowMinimizeButtonHint;
if (windowMaximizeButtonCheckBox->isChecked())
flags |= Qt::WindowMaximizeButtonHint;
if (windowCloseButtonCheckBox->isChecked())
flags |= Qt::WindowCloseButtonHint;
if (windowContextHelpButtonCheckBox->isChecked())
flags |= Qt::WindowContextHelpButtonHint;
if (windowShadeButtonCheckBox->isChecked())
flags |= Qt::WindowShadeButtonHint;
if (windowStaysOnTopCheckBox->isChecked())
flags |= Qt::WindowStaysOnTopHint;
if (windowStaysOnBottomCheckBox->isChecked())
flags |= Qt::WindowStaysOnBottomHint;
if (customizeWindowHintCheckBox->isChecked())
flags |= Qt::CustomizeWindowHint;
previewWindow->setWindowFlags(flags);我们还会确定哪些提示已被选中,并使用“或”运算符将其添加到flags 中。我们使用flags 来设置预览窗口的窗口标志。
QPoint pos = previewWindow->pos();
if (pos.x() < 0)
pos.setX(0);
if (pos.y() < 0)
pos.setY(0);
previewWindow->move(pos);
previewWindow->showNormal();
}我们调整预览窗口的位置。之所以这样做,是因为在某些平台上,对窗口边框的操作可能会在不知不觉中导致窗口位置发生变化。如果窗口位于屏幕的左上角,部分内容可能无法显示。 因此,我们调整小部件的位置,以确保即使发生这种情况,窗口仍会保持在屏幕边界内。最后,我们调用QWidget::show() 确保预览窗口可见。
void ControllerWindow::createTypeGroupBox()
{
typeGroupBox = new QGroupBox(tr("Type"));
windowRadioButton = createRadioButton(tr("Window"));
dialogRadioButton = createRadioButton(tr("Dialog"));
sheetRadioButton = createRadioButton(tr("Sheet"));
drawerRadioButton = createRadioButton(tr("Drawer"));
popupRadioButton = createRadioButton(tr("Popup"));
toolRadioButton = createRadioButton(tr("Tool"));
toolTipRadioButton = createRadioButton(tr("Tooltip"));
splashScreenRadioButton = createRadioButton(tr("Splash screen"));
windowRadioButton->setChecked(true);
QGridLayout *layout = new QGridLayout;
layout->addWidget(windowRadioButton, 0, 0);
layout->addWidget(dialogRadioButton, 1, 0);
layout->addWidget(sheetRadioButton, 2, 0);
layout->addWidget(drawerRadioButton, 3, 0);
layout->addWidget(popupRadioButton, 0, 1);
layout->addWidget(toolRadioButton, 1, 1);
layout->addWidget(toolTipRadioButton, 2, 1);
layout->addWidget(splashScreenRadioButton, 3, 1);
typeGroupBox->setLayout(layout);
}私有函数createTypeGroupBox() 由构造函数调用。
首先,我们创建一个组框,然后针对窗口标志中每种可用的类型,创建一个单选按钮(使用私有函数createRadioButton() )。我们将Qt::Window 设为初始应用的类型。我们将单选按钮放入QGridLayout 中,并将该布局安装到组框上。
我们不包含默认的Qt::Widget 类型。原因是它的行为与其他类型略有不同。如果未为某个小部件指定类型,且它没有父窗口,则该小部件即为窗口。但是,如果它有父窗口,则它就是标准子小部件。 其他类型均为顶级窗口,而由于提示仅对顶级窗口生效,因此我们放弃了Qt::Widget 类型。
void ControllerWindow::createHintsGroupBox()
{
hintsGroupBox = new QGroupBox(tr("Hints"));
msWindowsFixedSizeDialogCheckBox =
createCheckBox(tr("MS Windows fixed size dialog"));
x11BypassWindowManagerCheckBox =
createCheckBox(tr("X11 bypass window manager"));
framelessWindowCheckBox = createCheckBox(tr("Frameless window"));
windowNoShadowCheckBox = createCheckBox(tr("No drop shadow"));
windowTitleCheckBox = createCheckBox(tr("Window title"));
windowSystemMenuCheckBox = createCheckBox(tr("Window system menu"));
windowMinimizeButtonCheckBox = createCheckBox(tr("Window minimize button"));
windowMaximizeButtonCheckBox = createCheckBox(tr("Window maximize button"));
windowCloseButtonCheckBox = createCheckBox(tr("Window close button"));
windowContextHelpButtonCheckBox =
createCheckBox(tr("Window context help button"));
windowShadeButtonCheckBox = createCheckBox(tr("Window shade button"));
windowStaysOnTopCheckBox = createCheckBox(tr("Window stays on top"));
windowStaysOnBottomCheckBox = createCheckBox(tr("Window stays on bottom"));
customizeWindowHintCheckBox= createCheckBox(tr("Customize window"));
QGridLayout *layout = new QGridLayout;
layout->addWidget(msWindowsFixedSizeDialogCheckBox, 0, 0);
layout->addWidget(x11BypassWindowManagerCheckBox, 1, 0);
layout->addWidget(framelessWindowCheckBox, 2, 0);
layout->addWidget(windowNoShadowCheckBox, 3, 0);
layout->addWidget(windowTitleCheckBox, 4, 0);
layout->addWidget(windowSystemMenuCheckBox, 5, 0);
layout->addWidget(customizeWindowHintCheckBox, 6, 0);
layout->addWidget(windowMinimizeButtonCheckBox, 0, 1);
layout->addWidget(windowMaximizeButtonCheckBox, 1, 1);
layout->addWidget(windowCloseButtonCheckBox, 2, 1);
layout->addWidget(windowContextHelpButtonCheckBox, 3, 1);
layout->addWidget(windowShadeButtonCheckBox, 4, 1);
layout->addWidget(windowStaysOnTopCheckBox, 5, 1);
layout->addWidget(windowStaysOnBottomCheckBox, 6, 1);
hintsGroupBox->setLayout(layout);
}私有函数 `createHintsGroupBox() ` 也会在构造函数中被调用。
同样,我们首先创建一个组框。然后,针对窗口标志中可用的每项提示,我们使用私有函数createCheckBox() 创建一个复选框。我们将这些复选框放入QGridLayout 中,并将其布局安装到组框上。
QCheckBox *ControllerWindow::createCheckBox(const QString &text)
{
QCheckBox *checkBox = new QCheckBox(text);
connect(checkBox, &QCheckBox::clicked,
this, &ControllerWindow::updatePreview);
return checkBox;
}私有函数createCheckBox() 是从createHintsGroupBox() 中调用的。
我们只需使用给定的文本创建一个QCheckBox ,将其连接到私有updatePreview() 的插槽,并返回该复选框的指针。
QRadioButton *ControllerWindow::createRadioButton(const QString &text)
{
QRadioButton *button = new QRadioButton(text);
connect(button, &QRadioButton::clicked,
this, &ControllerWindow::updatePreview);
return button;
}在私有函数createRadioButton() 中,我们会使用给定的文本创建一个QRadioButton ,并将其连接到私有槽updatePreview() 。该函数由createTypeGroupBox() 调用,并返回该按钮的指针。
PreviewWindow 类定义
class PreviewWindow : public QWidget
{
Q_OBJECT
public:
PreviewWindow(QWidget *parent = nullptr);
void setWindowFlags(Qt::WindowFlags flags);
private:
QTextEdit *textEdit;
QPushButton *closeButton;
};PreviewWindow 类继承自QWidget 。这是一个自定义控件,用于在只读文本编辑器中显示当前设置的窗口标志名称。该类还提供了一个用于关闭窗口的QPushbutton按钮。
我们重写了构造函数以创建Close 按钮和文本编辑器,并重写了QWidget::setWindowFlags()函数以显示窗口标志的名称。

PreviewWindow 类的实现
PreviewWindow::PreviewWindow(QWidget *parent)
: QWidget(parent)
{
textEdit = new QTextEdit;
textEdit->setReadOnly(true);
textEdit->setLineWrapMode(QTextEdit::NoWrap);
closeButton = new QPushButton(tr("&Close"));
connect(closeButton, &QPushButton::clicked,
this, &PreviewWindow::close);
QVBoxLayout *layout = new QVBoxLayout;
layout->addWidget(textEdit);
layout->addWidget(closeButton);
setLayout(layout);
setWindowTitle(tr("Preview"));
}在构造函数中,我们首先创建一个QTextEdit ,并确保其为只读状态。
我们还通过调用QTextEdit::setLineWrapMode()函数,禁止文本编辑器中的任何换行。其结果是,当窗口标志的名称超过编辑器的宽度时,会出现一条水平滚动条。这是一个合理的解决方案,因为我们构建显示文本时使用了内置的换行符。如果无法保证换行符的存在,那么使用另一个QTextEdit::LineWrapMode 可能更为合理。
随后,我们创建Close 按钮,并在设置窗口标题之前,将这两个控件都放入QVBoxLayout 中。
void PreviewWindow::setWindowFlags(Qt::WindowFlags flags)
{
QWidget::setWindowFlags(flags);
QString text;
Qt::WindowFlags type = (flags & Qt::WindowType_Mask);
if (type == Qt::Window)
text = "Qt::Window";
else if (type == Qt::Dialog)
text = "Qt::Dialog";
else if (type == Qt::Sheet)
text = "Qt::Sheet";
else if (type == Qt::Drawer)
text = "Qt::Drawer";
else if (type == Qt::Popup)
text = "Qt::Popup";
else if (type == Qt::Tool)
text = "Qt::Tool";
else if (type == Qt::ToolTip)
text = "Qt::ToolTip";
else if (type == Qt::SplashScreen)
text = "Qt::SplashScreen";
if (flags & Qt::MSWindowsFixedSizeDialogHint)
text += "\n| Qt::MSWindowsFixedSizeDialogHint";
if (flags & Qt::X11BypassWindowManagerHint)
text += "\n| Qt::X11BypassWindowManagerHint";
if (flags & Qt::FramelessWindowHint)
text += "\n| Qt::FramelessWindowHint";
if (flags & Qt::NoDropShadowWindowHint)
text += "\n| Qt::NoDropShadowWindowHint";
if (flags & Qt::WindowTitleHint)
text += "\n| Qt::WindowTitleHint";
if (flags & Qt::WindowSystemMenuHint)
text += "\n| Qt::WindowSystemMenuHint";
if (flags & Qt::WindowMinimizeButtonHint)
text += "\n| Qt::WindowMinimizeButtonHint";
if (flags & Qt::WindowMaximizeButtonHint)
text += "\n| Qt::WindowMaximizeButtonHint";
if (flags & Qt::WindowCloseButtonHint)
text += "\n| Qt::WindowCloseButtonHint";
if (flags & Qt::WindowContextHelpButtonHint)
text += "\n| Qt::WindowContextHelpButtonHint";
if (flags & Qt::WindowShadeButtonHint)
text += "\n| Qt::WindowShadeButtonHint";
if (flags & Qt::WindowStaysOnTopHint)
text += "\n| Qt::WindowStaysOnTopHint";
if (flags & Qt::WindowStaysOnBottomHint)
text += "\n| Qt::WindowStaysOnBottomHint";
if (flags & Qt::CustomizeWindowHint)
text += "\n| Qt::CustomizeWindowHint";
textEdit->setPlainText(text);
}在我们对setWindowFlags() 函数的重写中,首先使用QWidget::setWindowFlags()函数设置控件的标志。然后遍历可用的窗口标志,创建一个包含标志名称的文本,该文本与flags 参数相匹配。最后,在控件的文本编辑器中显示该文本。
© 2026 The Qt Company Ltd. Documentation contributions included herein are the copyrights of their respective owners. The documentation provided herein is licensed under the terms of the GNU Free Documentation License version 1.3 as published by the Free Software Foundation. Qt and respective logos are trademarks of The Qt Company Ltd. in Finland and/or other countries worldwide. All other trademarks are property of their respective owners.