Qt 是目前最先进、最完整的跨平台C++开发工具。它不仅完全实现了一次编写,所有平台无差别运行,更提供了几乎所有开发过程中需要用到的工具。如今,Qt已被运用于超过70个行业、数千家企业,支持数百万设备及应用。
窗口标志要么是类型,要么是提示。类型用于为小部件指定各种窗口系统属性,一个小部件只能有一种类型,默认是Qt::Widget,但是小部件可以有零个或多个提示;提示用于自定义顶级窗口的外观。
小部件的标志存储在Qt::WindowFlags类型中,该类型存储标志的OR组合。
点击获取Qt Widget组件下载
这个例子由两个类组成:
- 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 = new PreviewWindow(this);
createTypeGroupBox();
createHintsGroupBox();
quitButton = new QPushButton(tr("&Quit"));
connect(quitButton, &QPushButton::clicked,
qApp, &QCoreApplication::quit);
QHBoxLayout *bottomLayout = new QHBoxLayout;
bottomLayout->addStretch();
bottomLayout->addWidget(quitButton);
QHBoxLayout *mainLayout = new QHBoxLayout;
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标志,然后确定要检查的类型并将其添加到标志中。
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操作符,使用标志来设置预览窗口的窗口标志。
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()调用,并返回一个指向按钮的指针。
未完待续,精彩下期继续......
Qt Widget组件推荐
- QtitanRibbon - Ribbon UI组件:是一款遵循Microsoft Ribbon UI Paradigm for Qt技术的Ribbon UI组件,QtitanRibbon致力于为Windows、Linux和Mac OS X提供功能完整的Ribbon组件。
- QtitanChart - Qt类图表组件:是一个C ++库,代表一组控件,这些控件使您可以快速地为应用程序提供漂亮而丰富的图表。
- QtitanDataGrid - Qt网格组件:提供了一套完整的标准 QTableView 函数和传统组件无法实现的独特功能。使您能够将不同来源的各类数据加载到一个快速、灵活且功能强大的可编辑网格中,支持排序、分组、报告、创建带状列、拖放按钮和许多其他方便的功能。
- QtitanDocking:允许您像 Visual Studio 一样为您的伟大应用程序配备可停靠面板和可停靠工具栏。黑色、白色、蓝色调色板完全支持 Visual Studio 2019 主题!