✿3-The Basics-使用Qt Widgets进行GUI设计

本文深入讲解QtWidgets模块,包括使用QtDesigner创建UI,管理布局,构建自定义部件,以及使用Qt样式表和自定义主题。通过实例展示了如何使用QLayout管理小部件布局,创建自定义小部件插件,以及应用QSS和自定义样式。此外,还介绍了如何在Qt中使用小部件、窗口和对话框,为GUI开发提供全面指导。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


Qt Widgets是一个模块,它提供了一组用于构建经典UI的用户界面(UI)元素。在本章中,你将了解 Qt Widgets模块,并了解基本小部件。我们将了解什么是小部件,以及可用于创建图形用户界面(GUI)的各种小部件。除此之外,还将向你介绍 Qt Designer的布局,并学习如何创建自己的自定义控件。我们将仔细研究Qt在轻松设计外观光滑的GUI时能为我们提供什么。在本章的开头,你将了解Qt提供的小部件类型及其功能。之后,我们将完成一系列步骤,并使用Qt设计我们的第一个表单应用程序。然后,你将学习样式表、Qt样式表( Qt Style Sheets)(QSS文件)和主题化。

本章将介绍以下主要主题:

  • 介绍Qt小部件
  • 使用Qt Designer创建UI
  • 管理布局
  • 创建自定义小部件
  • 创建Qt样式表和自定义主题
  • 探索自定义样式
  • 使用小部件、窗口和对话框

本章结束时,你将了解GUI元素及其相应的C++类的基础知识,如何在不编写一行代码的情况下创建自己的UI,以及如何使用样式表自定义UI的外观。

介绍Qt widgets

widget(小部件)是GUI的基本元素,它也被称为UI控件。它从底层平台接受不同的用户事件,例如鼠标和键盘事件(以及其他事件)。我们使用不同的小部件创建UI。曾经有一段时间,所有GUI控件都是从头开始编写的。Qt小部件通过开发带有现成GUI控件的桌面GUI来减少时间,Qt广泛使用继承的概念。所有小部件都继承自QObjectQWidget是一个基本的小部件,是所有UI小部件的基类;它包含描述小部件所需的大多数属性,以及几何体、颜色、鼠标、键盘行为、工具提示等属性。让我们看看下图中的QWidget继承层次结构:

  • QPushButton 用于命令应用程序执行特定操作。
  • QCheckBox 允许用户进行二进制选择。
  • QRadioButton 允许用户从一组相互排斥的选项中仅做出一个选择。
  • QFrame 显示一个框架。
  • QLabel 用于显示文本或图像。
  • QLineEdit 允许用户输入和编辑单行纯文本。
  • QTabWidget 用于在选项卡式窗口小部件的堆栈中显示与每个选项卡相关的页面。

使用Qt小部件的优点之一是它的继承系统。从QObject继承的任何对象都具有父子关系。这种关系为开发人员提供了许多便利,例如:

  • 当一个小部件被销毁时,由于父子层次结构,它的所有子部件也已经被销毁了。这样可以避免内存泄漏。
  • 通过使用findChild()findChildren()可以找到给定QWidget类的子类。
  • Qwidget中的子部件会自动出现在父部件中。

典型的C++程序在主main()函数返回时终止,但在GUI应用程序中,我们不能这样做,或者应用程序将无法使用。因此,我们需要GUI一直存在,直到用户关闭窗口。为了实现这一点,程序应该在循环中运行,直到发生这种情况。GUI应用程序等待用户输入事件。

让我们使用简单的GUI程序,使用QLabel显示一段文本:

#include <QApplication> 
#include <QLabel> 
int main(int argc, char *argv[]) { 
	QApplication app(argc, argv); 
	QLabel myLabel; 
	myLabel.setText("Hello World!"); 
	myLabel.show(); 
	return app.exec(); 
}

记住在.pro文件中添加以下行,用于启用Qt Widgets模块:

QT += widgets

使用Qt Designer创建UI


Qt Widgets模块附带了现成的小部件。Qt提供了一个通过拖放方法创建UI的选项。让我们通过简单地将这些小部件从小部件框区域拖动到表单编辑器区域来探索它们。在项目到达表单编辑器区域之前,不要释放鼠标或触控板。下面的屏幕截图显示了小部件框部分中可用的不同类型的小部件。我们在表单编辑器区域中添加了一些现成的小部件,如标签、按钮、单选按钮、复选框、组合框、进度条和行编辑。这些小部件是非常常用的小部件。你可以在 [属性编辑器] 中浏览特定于小部件的属性。

你可以预览UI:Tools->Form Editor->Preview

还可以查看UI对应的C++代码:Tools->C+±>Inspect C++ Code Model…

管理布局

Qt提供了一组方便的布局管理类,可以在另一个小部件中自动排列子小部件,以确保UI保持可用。QLayout类是所有布局管理器的基类。还可以通过重新实现setGeometry()、sizeHint()、addItem()、itemAt()、takeAt()和minimumSize()函数来创建自己的布局管理器。请注意,一旦删除布局管理器,布局管理也将停止。以下列表简要介绍了主要布局类:

  • QVBoxLayout 垂直排列小部件。
  • QHBoxLayout 水平排列小部件。
  • QGridLayout 在网格中布局小部件。
  • QFormLayout 管理各种形式的输入小部件及其相关标签。
  • QStackedLayout 提供了一组小部件,一次只能看到一个小部件。

QLayout通过从QObject和QLayoutItem继承来使用多个继承。QLayout的子类是QBoxLayout、QGridLayout、QFormLayout和QStackedLayout。QVBoxLayout和QHBoxLayout继承自QBoxLayout,并添加了方向信息。让我们使用Qt Designer模块来布置几个QPushButtons。

QVBoxLayout:

对应的完整C++代码:

#include <QtCore/QVariant>
#include <QtWidgets/QAction>
#include <QtWidgets/QApplication>
#include <QtWidgets/QButtonGroup>
#include <QtWidgets/QHeaderView>
#include <QtWidgets/QMainWindow>
#include <QtWidgets/QMenuBar>
#include <QtWidgets/QPushButton>
#include <QtWidgets/QStatusBar>
#include <QtWidgets/QToolBar>
#include <QtWidgets/QVBoxLayout>
#include <QtWidgets/QWidget>

QT_BEGIN_NAMESPACE

class Ui_MainWindow {
public:
    QWidget *centralWidget;
    QVBoxLayout *verticalLayout;
    QPushButton *pushButton;
    QPushButton *pushButton_2;
    QPushButton *pushButton_3;
    QPushButton *pushButton_4;
    QMenuBar *menuBar;
    QToolBar *mainToolBar;
    QStatusBar *statusBar;

    void setupUi(QMainWindow *MainWindow) {
        if (MainWindow->objectName().isEmpty())
            MainWindow->setObjectName(QStringLiteral("MainWindow"));
        MainWindow->resize(378, 282);
        centralWidget = new QWidget(MainWindow);
        centralWidget->setObjectName(QStringLiteral("centralWidget"));
        verticalLayout = new QVBoxLayout(centralWidget);
        verticalLayout->setSpacing(6);
        verticalLayout->setContentsMargins(11, 11, 11, 11);
        verticalLayout->setObjectName(QStringLiteral("verticalLayout"));
        pushButton = new QPushButton(centralWidget);
        pushButton->setObjectName(QStringLiteral("pushButton"));

        verticalLayout->addWidget(pushButton);

        pushButton_2 = new QPushButton(centralWidget);
        pushButton_2->setObjectName(QStringLiteral("pushButton_2"));
        pushButton_2->setMinimumSize(QSize(366, 15));

        verticalLayout->addWidget(pushButton_2);

        pushButton_3 = new QPushButton(centralWidget);
        pushButton_3->setObjectName(QStringLiteral("pushButton_3"));

        verticalLayout->addWidget(pushButton_3);

        pushButton_4 = new QPushButton(centralWidget);
        pushButton_4->setObjectName(QStringLiteral("pushButton_4"));

        verticalLayout->addWidget(pushButton_4);

        MainWindow->setCentralWidget(centralWidget);
        menuBar = new QMenuBar(MainWindow);
        menuBar->setObjectName(QStringLiteral("menuBar"));
        menuBar->setGeometry(QRect(0, 0, 378, 17));
        MainWindow->setMenuBar(menuBar);
        mainToolBar = new QToolBar(MainWindow);
        mainToolBar->setObjectName(QStringLiteral("mainToolBar"));
        MainWindow->addToolBar(Qt::TopToolBarArea, mainToolBar);
        statusBar = new QStatusBar(MainWindow);
        statusBar->setObjectName(QStringLiteral("statusBar"));
        MainWindow->setStatusBar(statusBar);

        retranslateUi(MainWindow);

        QMetaObject::connectSlotsByName(MainWindow);
    } // setupUi

    void retranslateUi(QMainWindow *MainWindow) {
        MainWindow->setWindowTitle(QApplication::translate("MainWindow", "MainWindow", Q_NULLPTR));
        pushButton->setText(QApplication::translate("MainWindow", "PushButton1", Q_NULLPTR));
        pushButton_2->setText(QApplication::translate("MainWindow", "PushButton2", Q_NULLPTR));
        pushButton_3->setText(QApplication::translate("MainWindow", "PushButton3", Q_NULLPTR));
        pushButton_4->setText(QApplication::translate("MainWindow", "PushButton4", Q_NULLPTR));
    } // retranslateUi
};

namespace Ui {
    class MainWindow: public Ui_MainWindow {};
} // namespace Ui

QT_END_NAMESPACE

这个程序演示了如何使用垂直布局对象。请注意,QWidget实例widget将成为应用程序的主窗口。在这里,布局被直接设置为顶层布局。添加到addWidget()方法的第一个按钮占据版面的顶部,而最后一个按钮占据版面的底部。
如果没有在QWidget构造函数中设置父窗口,那么以后必须使用QWidget::setLayout()安装布局并重新分配到小部件实例。

QGridLayout:
你还可以通过C++代码动态添加网格布局,如下面的代码片段所示:

QWidget *widget = new QWidget; 
QPushButton *pushBtn1 = new QPushButton( "Push Button 1"); 
QPushButton *pushBtn2 = new QPushButton( "Push Button 2"); 
QPushButton *pushBtn3 = new QPushButton( "Push Button 3"); 
QPushButton *pushBtn4 = new QPushButton( "Push Button 4"); 
QGridLayout *gridLayout = new QGridLayout(widget); 
gridLayout->addWidget(pushBtn1); 
gridLayout->addWidget(pushBtn2); 
gridLayout->addWidget(pushBtn3); 
gridLayout->addWidget(pushBtn4); 
widget->show();

创建自定义部件

自定义小部件可以是一个或多个放置在一起的Qt小部件的组合,也可以从头开始编写。我们将从QLabel创建一个简单的标签小部件,作为我们的第一个自定义小部件。一个自定义小部件集合可以有多个自定义小部件。
New->Other Project->Qt Custom Designer Widget,步骤如下:



工程目录:

展开Project Explorer视图并打开mylabel.h文件。我们将修改内容以扩展功能。在自定义小部件类名之前添加QDESIGNER_WIDGET_EXPORT宏,以确保在动态链接库(dynamic-link library:DLL)或共享库中正确导出该类。你的自定义小部件可能在没有此宏的情况下工作,但添加此宏是一个很好的做法。插入宏后,必须将#include<QtDesigner>添加到头文件中。mylabel.h修改如下:

#ifndef MYLABEL_H
#define MYLABEL_H
#include <QLabel>
#include <QtDesigner>
class QDESIGNER_WIDGET_EXPORT MyLabel: public QLabel {
    Q_OBJECT
    Q_PROPERTY(bool multiLine READ isMultiLine WRITE setMultiLine)
    Q_PROPERTY(Qt::GlobalColor color READ getColor WRITE setColor)
private:
    bool m_isMultiLine = false;
    Qt::GlobalColor m_color = Qt::GlobalColor::black;
public:
    MyLabel(QWidget *parent = 0);
    void setMultiLine(bool isMultiLine);
    bool isMultiLine() const { return m_isMultiLine; }
    void setColor(Qt::GlobalColor color);
    Qt::GlobalColor getColor() { return m_color; }
};
#endif

mylabel.cpp代码如下:

#include "mylabel.h"
MyLabel::MyLabel(QWidget *parent): QLabel(parent) {}
void MyLabel::setMultiLine(bool isMultiLine) { m_isMultiLine = isMultiLine; }
void MyLabel::setColor(Qt::GlobalColor color) { m_color = color; }

注:
在某些平台上,构建系统可能会删除Qt Designer模块创建新小部件所需的符号,使其无法使用。使用QDESIGNER_WIDGET_EXPORT宏可确保符号保留在这些平台上。这在创建跨平台库时非常重要。在其他平台上没有副作用。

mylabelplugin.h

#ifndef MYLABELPLUGIN_H
#define MYLABELPLUGIN_H
#include <QDesignerCustomWidgetInterface>

class MyLabelPlugin : public QObject, public QDesignerCustomWidgetInterface {
    Q_OBJECT
    Q_INTERFACES(QDesignerCustomWidgetInterface)
public:
    MyLabelPlugin(QObject *parent = 0);
    
    bool isContainer() const;
    bool isInitialized() const;
    QIcon icon() const;
    QString domXml() const;
    QString group() const;
    QString includeFile() const;
    QString name() const;
    QString toolTip() const;
    QString whatsThis() const;
    QWidget *createWidget(QWidget *parent);
    void initialize(QDesignerFormEditorInterface *core);
private:
    bool m_initialized;
};
#endif

可以看到MyLabelPlugin类继承自类QDesignerCustomWidgetInterface,这个类允许Qt Designer去访问和创建自定义小部件。
请注意,你得更改头文件如下,以避免depressed warnings,如下:

修改为如下,则不报depressed warnings:

#include <QtUiPlugin/QDesignerCustomWidgetInterface>

mylabelplugin.cpp

#include "mylabel.h"
#include "mylabelplugin.h"
#include <QtPlugin>
MyLabelPlugin::MyLabelPlugin(QObject *parent): QObject(parent) {
    m_initialized = false;
}
void MyLabelPlugin::initialize(QDesignerFormEditorInterface * /* core */) {
    if (m_initialized)
        return;
    // Add extension registrations, etc. here
    m_initialized = true;
}
bool MyLabelPlugin::isInitialized() const { return m_initialized; }
QWidget *MyLabelPlugin::createWidget(QWidget *parent) { return new MyLabel(parent); }
QString MyLabelPlugin::name() const { return QLatin1String("MyLabel"); }
QString MyLabelPlugin::group() const { return QLatin1String(""); }
QIcon MyLabelPlugin::icon() const { return QIcon(); }
QString MyLabelPlugin::toolTip() const { return QLatin1String(""); }
QString MyLabelPlugin::whatsThis() const { return QLatin1String(""); }
bool MyLabelPlugin::isContainer() const { return false; }
QString MyLabelPlugin::domXml() const {
    return QLatin1String("<widget class=\"MyLabel\" name=\"myLabel\">\n</widget>\n");
}
QString MyLabelPlugin::includeFile() const { return QLatin1String("mylabel.h"); }

#if QT_VERSION < 0x050000
Q_EXPORT_PLUGIN2(mylabelplugin, MyLabelPlugin)
#endif

请不要删除生成的函数。你可以给name()、group()、icon()指定值。注意,如果你不给icon()指定值,Qt Designer会使用默认的Qt icon。

你可以看到,isContainer()返回false在MyLabelMyFrame返回true。因为MyLabel不是设计用来作为其他小部件的容器的,而MyFrame在创建时就勾选了“The widget is a container”。
Qt Designer调用createWidget()去生成一个MyLabelMyFrame的实例。

我们指定myframeplugin.cpp中的group()值,如下:

QString MyFramePlugin::group() const { return QLatin1String("My Container"); }

要创建具有自定义几何体或任何其他属性的小部件,则在domXML()方法中指定这些属性。该函数返回可扩展标记语言(XML)片段,小部件工厂(the widget factory)使用该片段创建具有定义属性的自定义小部件。
让我们指定MyLable宽=100px,高=16px,如下:

QString MyLabelPlugin::domXml() const { 
	return "<ui language=\"c++\" displayname=\"MyLabel\">\n" 
		   		"<widget class=\"MyLabel\" name=\"myLabel\">\n" 
					"<property name=\"geometry\">\n" 
						"<rect>\n" 
							"<x>0</x>\n" 
							"<y>0</y>\n" 
							"<width>100</width>\n" 
							"<height>16</height>\n" 
						"</rect>\n" 
					"</property>\n" 
					"<property name=\"text\">\n" 
						"<string>MyLabel</string>\n" 
					"</property>\n" 
				"</widget>\n" 
			"</ui>\n";
}

现在我们看看MyWidgets.pro文件,如下。
它包含qmake所需的所有信息去构建自定义小部件集合库。

#MyWidgets.pro
CONFIG      += plugin debug_and_release
TARGET      = $$qtLibraryTarget(mylabelplugin)
TEMPLATE    = lib
HEADERS     = mylabelplugin.h
SOURCES     = mylabelplugin.cpp
RESOURCES   = icons.qrc
LIBS        += -L.
greaterThan(QT_MAJOR_VERSION, 4) {
    QT += designer
} else {
    CONFIG += designer
}
target.path = $$[QT_INSTALL_PLUGINS]/designer
INSTALLS    += target
include(mylabel.pri)

可以看到,这个工程是一个库类型,并且被配置用作一个插件。

现在,让我们运行qmake并在Release模式下构建这个库。
请添加图片描述
Build后,在项目所在目录生成如下文件夹:
请添加图片描述
在Windows平台上,可以手动将新生成的文件夹里的release目录下的mywidgetcollectionplugin.dll复制到D:\Qt\6.0.0\mingw81_64\plugins\designer路径下。这个路径及文件扩展名依不同操作系统而异。如果不做这样的拷贝操作,就无法在designer.exe窗口看到我们自定义的插件。

此时,我们已经创建了我们自定义的插件。
现在,在D:\Qt\6.0.0\mingw81_64\bin目录下找到designer.exe,双击打开。
可以看到我们自定义的部件:

单击“创建”按钮,将MyLabel拖到MyFrame里面。

你还可以在属性编辑器中看到创建的MyLabel的属性:自定义QLabel下的multiLine、color属性。

你现在已经成功创建了你的自定义部件,并拥有新的属性。你也可以通过组合不同的部件创建更复杂的部件。

你还可以在以下Qt文档链接中找到带有示例的详细说明:
https://doc.qt.io/qt-6/designer-creating-custom-widgets.html

创建Qt样式表和自定义主题

Qt提供了几种定制UI外观的方法。Qt样式表(Qt Style Sheet)是在不进行复杂编码的情况下改变小部件外观的最简单方法之一。Qt样式表语法与超文本标记语言(HTML)/级联样式表(CSS)语法相同。样式表由一系列样式规则组成。样式规则由选择器和声明组成。选择器指定将受样式规则影响的小部件,声明指定小部件的属性。样式规则的声明部分是一个属性列表,作为键值对,包含在{}中,用分号分隔。

让我们来看一个简单的QPushButton样式表语法:

QPushButton{color:green; background-color:rgb(193,255,216);}

可以在Qt Designer中用样式表编辑器来应用样式表,我们使用下面的样式代码来让按钮更好看:

QPushButton { 
	background-color: rgb(193, 255, 216); 
	border-width: 2px; 
	border-radius: 6; 
	border-color: lime; 
	border-style: solid; 
	padding: 2px; 
	min-height: 2.5ex; 
	min-width: 10ex; 
} 
QPushButton:hover { background-color: rgb(170, 255, 127); } 
QPushButton:pressed {background-color: rgb(170, 255, 127); font: bold; }


还可以为每个按钮创建不同的样式,并通过在样式表中提及按钮的对象名称,将样式应用于各个按钮,如下所示:

QPushButton#pushButtonID

要了解有关样式表及其用法的更多信息,请阅读以下链接中的文档:
https://doc.qt.io/qt-6/stylesheet-reference.html
https://doc.qt.io/qt-6/stylesheet-syntax.html
https://doc.qt.io/qt-6/stylesheet-customizing.html

CSS选择符主要有3种:HTML选择符、class选择符 和 id选择符。
1.HTML选择符:以HTML标签作为选择符。如:

h1 {text-align: center; color: blue}

<h1>一级标题居中蓝色</h1>

2.class选择符:使用HTML标签的class属性值作为选择符。定义class选择符时,前面要加“.”标志。如:

.title {text-align: center; color: blue}

<p class="title">蓝色的段落</p>
<h1 class="title">蓝色的标题</h1>

3.id选择符:使用HTML标签的id属性值作为选择符。定义id选择符时,前面要加“#”标志。如:

#red {color:red;}
#green {color:green;}

<p id="red">这个段落是红色</p>
<p id="green">这个段落是绿色</p>
使用QSS文件

你可以组合所有的样式表于一个.qss文件中。QSS文件类似于.css文件,其中包含GUI元素的外观定义,如颜色、背景色、字体和鼠标交互行为。可以使用.qss文件扩展名创建新的样式表文件,然后将其添加到资源文件(.qrc)。你可能还没有应用于所有项目的.ui文件。GUI控件可以通过代码动态创建。可以将样式表应用于小部件或整个应用程序,如下面的代码段所示。这是我们为自定义小部件或表单所做的:

MyWidget::MyWidget(QWidget* parent): QWidget(parent) {
	setStyleSheet("QWidget{background-color:green}");
}

下面是我们如何将它应用于整个应用程序的:

#include "mywidgets.h"
#include <QApplication>
#include <QFile>
int main(int argc, char* argv[]) {
	QApplication app(argc, argv);
	QFile file(":/qss/default.qss");
	file.open(QFile::ReadOnly);
	QString styleSheet = QLatin1String(file.readAll());
	app.setStyleSheet(styleSheet);
	Widget mywidget;
	mywidget.show();
	return app.exec();
}

前面的程序演示了如何为整个Qt GUI应用程序使用样式表文件。你需要添加.qss文件到资源目录。使用QFile打开.qss文件,并将定制的QSS样式作为参数传递给QApplication对象上的setStyleSheet()方法。你将看到所有屏幕都应用了样式表。

在本节中,你了解了如何使用样式表定制应用程序的外观,但有更多方法可以更改应用程序的外观。这些方法取决于你的项目需要。

探索自定义样式

Qt提供了几个QStyle子类,它们模拟Qt支持的不同平台的样式。这些样式在Qt GUI模块中很容易获得。你可以构建自己的自定义样式,并将其导出为插件。Qt使用QStyle呈现Qt小部件,以确保它们的外观和感觉与本机小部件相同。

在Unix发行版上,可以通过运行以下命令为应用程序获取Windows样式的UI:

$./helloworld -style windows

你可以使用QWidget::setStyle()方法在单个小部件上设置样式。

创建自定义样式

通过创建自定义样式,可以自定义GUI的外观。创建自定义样式有两种不同的渠道。

  1. 在静态渠道中,可以对QStyle类进行子类化,并重新实现虚函数以提供所需的行为,或者从头重写QStyle类。QCommonStyle通常用作基类,而不是QStyle
  2. 在动态渠道中,可以将QProxyStyle子类化,并在运行时修改系统样式的行为。你还可以通过使用诸如drawPrimitive()drawItemText()drawControl()QStyle函数来开发支持样式的自定义小部件。

本节是一个高级Qt主题。你需要深入了解Qt才能创建自己风格的插件。如果你是初学者,你可以跳过这一节。你可以通过以下链接在Qt文档中了解QStyle类和自定义样式:https://doc.qt.io/qt-6/qstyle.html

使用自定义样式

有几种方法可以在Qt应用程序中应用自定义样式。最简单的方法是在创建QApplication对象之前调用QApplication::setStyle()静态函数,如下所示:

#include "customstyle.h" 
int main(int argc, char *argv[]) { 
	QApplication::setStyle(new CustomStyle); 
	QApplication app(argc, argv); 
	Widget helloworld; 
	helloworld.show(); 
	return app.exec(); 
}

还可以将自定义样式应用为命令行参数,如下所示:

>./customstyledemo -style customstyle

自定义样式可能很难实现,但可以更快、更灵活。QSS易于学习和实现,但性能可能会受到影响,尤其是在应用程序启动时,因为QSS解析可能需要时间。你可以选择对你或你的组织方便的方法。现在,我们已经学习了如何定制GUI。

使用小部件、窗口和对话框

小部件是可以在屏幕上显示的GUI元素。这可能包括标签、按钮、列表视图、窗口、对话框等。所有小部件都在屏幕上向用户显示特定信息,其中大多数小部件允许用户通过键盘或鼠标进行交互。

窗口是没有其他父窗口小部件的顶级窗口小部件。通常,除非指定了任何窗口标志,否则窗口都有标题栏和边框。窗口样式和某些策略由底层窗口系统决定。Qt中的一些常见窗口类是QMainWindowQMessageBoxQDialog。主窗口通常遵循桌面应用程序的预定义布局,包括菜单栏、工具栏、中心小部件区域和状态栏。QMainWindow需要一个中心小部件,即使它只是一个占位符。其他组件可以在主窗口中移除。下图显示了QMainWindow的布局结构。我们通常调用show()方法来显示小部件或主窗口。

QMenuBar位于QMainWindow的顶部。你可以添加菜单选项,如文件、编辑、查看和帮助。在下面显示QMenuBar的屏幕截图中,有QToolBarQDockWidget提供了一个小部件,可以停靠在QMainWindow内部,也可以作为顶级窗口浮动。中心窗口小部件是主视图区域,你可以在其中添加表单或子窗口小部件。使用子窗口小部件创建自己的视图区域,然后调用setCentralWidget()

重要提示:
QMainWindow不应与QWindow混淆。QWindow是一个方便的类,表示底层窗口系统中的窗口。通常,应用程序的UI使用QWidgetQMainWindow。但是,如果希望保持最小的依赖关系,可以直接渲染到QWindow

对话框是用于提供通知或接收用户输入的临时窗口,通常有“确定”和“取消”按钮。QMessageBox是一种对话框,用于显示信息和警报,或向用户提问。通常,exec()方法用于显示对话框。该对话框显示为模式对话框,在用户关闭它之前本质上是阻塞的。可以使用以下代码段创建一个简单的消息框:

QMessageBox messageBox;
messageBox.setText("This is a simple QMessageBox.");
messageBox.exec();

值得注意的是,所有这些都是小部件。窗口是顶级小部件,对话框是一种特殊的窗口。

总结

本章介绍了Qt Widgets模块的基本原理以及如何创建自定义UI。在这里,你学习了使用Qt Designer设计和构建GUI。传统的桌面应用程序通常是用Qt设计器构建的。自定义小部件插件等功能允许你使用Qt Designer创建和使用自己的小部件集合。我们还讨论了使用样式表和样式定制应用程序的外观,以及小部件、窗口和对话框之间的用法和差异。现在,你可以创建一个带有扩展功能的自定义小部件的GUI应用程序,并为桌面应用程序创建自己的主题。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

itzyjr

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值