窗口标志示例
窗口标志示例展示了如何使用 Qt 中可用的窗口标志。
窗口标志既可以是一个类型,也可以是一个提示。类型用于为窗口部件指定各种窗口系统属性。一个窗口部件只能有一种类型,默认值是Qt::Widget 。不过,一个窗口部件可以有零个或多个提示。提示用于自定义顶层窗口的外观。
widget 的标志存储在Qt::WindowFlags 类型中,该类型存储标志的 OR 组合。
窗口标志示例截图
该示例由两个类组成:
ControllerWindow
是主程序窗口部件,允许用户选择可用的窗口标志,并在单独的预览窗口中显示效果。PreviewWindow
是自定义窗口部件,在只读文本编辑器中显示当前设置的窗口标志名称。
我们将首先回顾ControllerWindow
类,然后再看看PreviewWindow
类。
控制器窗口类定义
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(QWidget*parent) : QWidget(parent) { previewWindow= newPreviewWindow(this); createTypeGroupBox(); createHintsGroupBox(); quitButton= newQPushButton(tr("&Quit")); connect(quitButton, &QPushButton点击 qApp, &QCoreApplication::quit); QHBoxLayout*bottomLayout = newQHBoxLayout*mainLayout = new*mainLayout->addStretch();*mainLayout->addWidget(quitButton); QHBoxLayout*mainLayout = newQHBoxLayoutmainLayout->addWidget(typeGroupBox); mainLayout->addWidget(hintsGroupBox); mainLayout->addLayout(bottomLayout); setLayout(mainLayout); setWindowTitle(tr("Window Flags")); updatePreview(); }
在构造函数中,我们首先创建预览窗口。然后,我们使用私有createTypeGroupBox()
和createHintsGroupBox()
函数创建包含可用窗口标志的组框。此外,我们还创建了一个Quit 按钮。我们将按钮和一个可拉伸空间放在一个单独的布局中,以使按钮显示在WindowFlag
widget 的右下角。
最后,我们将按钮布局和两个组框添加到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);
我们还确定选中了哪些提示,并使用 OR 运算符将它们添加到flags
。我们使用flags
为预览窗口设置窗口标志。
QPoint pos = previewWindow->pos(); if (pos.x() < 0) pos.setX(0); if (pos.y() < 0) pos.setY(0); previewWindow->move(pos); previewWindow->show(); }
我们调整预览窗口的位置。这样做的原因是,在某些平台上,随意摆弄窗口的边框可能会导致窗口的位置发生变化。如果窗口位于屏幕的左上角,那么窗口的部分内容就可能不可见。因此,我们要调整窗口部件的位置,以确保在发生这种情况时,窗口能在屏幕边界内移动。最后,我们调用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()
调用,并返回一个指向按钮的指针。
预览窗口类定义
class PreviewWindow : public QWidget { Q_OBJECT public: PreviewWindow(QWidget *parent = nullptr); void setWindowFlags(Qt::WindowFlags flags); private: QTextEdit *textEdit; QPushButton *closeButton; };
PreviewWindow
类继承于QWidget 。它是一个自定义 widget,可在只读文本编辑器中显示当前设置的窗口标志名称。它还提供了一个用于关闭窗口的 QPushbutton 按钮。
我们重新实现了用于创建Close 按钮和文本编辑器的构造函数,以及用于显示窗口标志名称的QWidget::setWindowFlags() 函数。
预览窗口类的实现
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
参数匹配的标志名称的文本。最后,我们在 widgets 文本编辑器中显示文本。
© 2025 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.