22、GUI控件类---------常见界面组件类

GUI控件类

QWidget简介

所有界面组件类的直接或间接父类都是 QWidget。QWidget 的父类是 QObject 和 QPaintDevice,所以 QWidget 是多重继承的类。

QObject 支持元对象系统,其信号与槽机制为 GUI 编程中对象间通信提供了极大的便利。

QPaintDevice 是能使 QPainter 类在绘图设备上绘图的类。

我们可以新建一个Qt Widgets Application项目, 名字叫做01-QMainWindows

创建成功后,双击mainwindow.ui文件, 进入Designer界面。

  1. 红框1主要是控件区,包括常用的控件都罗列在这里。
  2. 绿框2主要是ui的布局区,可以拖动部件调整在布局中的位置,程序运行后会按照布局设计的样式展示。
  3. 黄框3主要是ui对象层级管理区,主要展示各个对象之间的层级关系。
  4. 篮筐4主要是属性编辑区,可以设计

我们在ui区可以看到MainWindow界面

我们观察QtDesigner界面左侧控件区, 会看到QWidget在Containers里,因为QWidget属于容器类型

大家可以直接拖动designer中的widget放入MainWindow界面里

然后在右侧的对象层级管理区能看到我们新增的widget

为了方便展示我们新增的widget,点击右侧对象层级管理中的widget,去右下方的属性管理器找到stylesheet样式表

点击右侧的小三角弹出编辑样式表,这个样式表就是设置控件样式的,包括颜色,大小等。我们添加背景颜色为绿色

点击ok保存,再次运行

这是最简单的利用Designer拖动实现界面创建的方式。

QWidget基本接口

显示和隐藏
  • show():显示窗口。
  • hide():隐藏窗口。
  • close():关闭窗口。
代码创建

我们也可通过代码创建一个widget,在main函数中将MainWindow展示逻辑去掉,替换成创建widget然后展示出来。

示例

展示一个窗口, 大家可以在main函数中创建这个QWidget,并展示出来,这是通过代码创建QWidget的方式。

cpp 复制代码
int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    QWidget widget;
    widget.show();
    return a.exec();
}
大小和位置
  • resize(int width, int height):调整窗口大小。
  • move(int x, int y):移动窗口到指定位置。
  • setGeometry(int x, int y, int width, int height):设置窗口的几何属性。
  • size():返回窗口的大小。
  • pos():返回窗口的位置。

练习

我们重新设置widget大小为800*600

将窗口移动到(100,100)位置

并且将窗口展示出来

cpp 复制代码
int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    QWidget widget;
    //重新设置大小为800*600
    widget.resize(800,600);
    //移动到(100,100)位置
    widget.move(100,100);
    widget.show();
    return a.exec();
}

添加资源文件

我们的一些界面会带有图标,为了添加图标,右键刚才创建的MainWindow项目弹出的菜单选择AddNew

选择Qt Resource

为资源文件命名为qrc

选择添加到项目

在项目目录里创建res文件夹,添加两个文件new.png和open.png

右键项目左侧目录数Resources下的qrc.qrc, 添加现有文件

在文件目录中选择我们刚才添加的图片文件

点击确定之后,可以看到项目结构目录下qrc文件下增加了图片资源

练习

将图片资源添加到项目中

使用资源

如果以后想要使用资源,可以右键对应的图片,在弹出的菜单选择copy path即可

代码中可以直接写这个路径作为资源路径进行加载

QMainWindow

QMainWindow是主窗口类,我们创建一个Qt Widgets Application项目,Qt Creator默认为我们生成的就是继承自QMainWindow的界面类并展示出来。

下图为QMainWindow的结构示意图

我们看下层级管理,

能看到几个控件

  1. menuBar 菜单栏
  2. mainToolBar 工具栏
  3. centralWidget 为中心控件
  4. widget为我们刚才添加的widget控件
  5. statusBar为状态栏
创建菜单

创建菜单可以通过ui创建,但是不够灵活,现在企业基本采用代码创建.

有时候MainWindow中没有菜单栏,可以通过ui添加,但不推荐,我们直接通过代码创建菜单栏,并将菜单栏设置到MainWindow中。

QMenuBar的构造函数接受一个QWidget作为其父节点

cpp 复制代码
QMenuBar(QWidget *parent = nullptr)

MainWindow 设置菜单栏的接口

cpp 复制代码
void QMainWindow::setMenuBar(QMenuBar *menuBar)

我们在MainWindow的构造函数中添加菜单栏

cpp 复制代码
//设置窗口标题
this->setWindowTitle("myWindow");
//重设窗口大小
this->resize(1100,700);
//创建菜单栏
QMenuBar *menuBar = new QMenuBar(this);
//添加菜单栏到主窗口中
this->setMenuBar(menuBar);

QMenu构造函数有两个,可接受文本作为菜单的名字。

cpp 复制代码
QMenu(QWidget *parent = nullptr)
QMenu(const QString &title, QWidget *parent = nullptr)

练习

接下来我们创建三个一级菜单(文件,编辑,构建)并添加到菜单栏里

cpp 复制代码
//创建文件菜单
QMenu *menu1 = new QMenu("文件",this);
//创建编辑菜单
QMenu *menu2 = new QMenu("编辑",this);
//创建构建菜单
QMenu *menu3 = new QMenu("构建",this);
//将菜单添加到菜单栏
menuBar->addMenu(menu1);
menuBar->addMenu(menu2);
menuBar->addMenu(menu3);

再次运行可看到窗口里添加了菜单栏

添加菜单项

菜单项在Qt中叫做QAction, QAction包含三种构造参数

cpp 复制代码
//接受一个参数,父节点
QAction(QObject *parent = nullptr)
//接受两个参数,菜单项的名字和其父节点
QAction(const QString &text, QObject *parent = nullptr)
//接受三个参数,菜单项的图标,菜单项的名字,父节点
QAction(const QIcon &icon, const QString &text, QObject *parent = nullptr)

QIcon的构造传入图片路径即可构造一个图标

cpp 复制代码
QIcon(const QString &fileName)

QMenu添加菜单项的接口

cpp 复制代码
void QMenu::addAction(Action *action)

QMenu可以为菜单项设置分割符

cpp 复制代码
QAction *QMenu::addSeparator()

练习

在新建菜单下添加菜单项,名字为"新建文件或项目"

在新建菜单下添加菜单项,名字为"打开文件或项目"

在新建菜单下添加分隔符,分隔符下添加菜单项,名字为退出

可以配合前面添加到资源文件为菜单项设置图标

实现如下效果

答案

cpp 复制代码
//创建菜单栏
QMenuBar *menuBar = new QMenuBar(this);
//添加菜单栏到主窗口中
this->setMenuBar(menuBar);

//创建文件菜单
QMenu *menu1 = new QMenu("文件",this);
//创建编辑菜单
QMenu *menu2 = new QMenu("编辑",this);
//创建构建菜单
QMenu *menu3 = new QMenu("构建",this);
//将菜单添加到菜单栏
menuBar->addMenu(menu1);
menuBar->addMenu(menu2);
menuBar->addMenu(menu3);
//创建新建菜单项
auto new_action = new QAction(QIcon(":/res/new.png"),"新建文件或项目",this);
//创建打开菜单项
auto open_action = new QAction(QIcon(":/res/open.png"),"打开文件或项目",this);
//创建退出菜单项
auto exit_action = new QAction("退出",this);
//添加新建菜单项
menu1->addAction(new_action);
//添加打开菜单项
menu1->addAction(open_action);
//添加分割符
menu1->addSeparator();
//添加退出菜单项
menu1->addAction(exit_action);
菜单项添加快捷键

我们可以通过QAction的函数setShortcut为菜单项添加快捷键

cpp 复制代码
void setShortcut(const QKeySequence &shortcut)

QKeySequence构造函数接受按键组成的宏,比如快捷键Ctrl+N

cpp 复制代码
action1->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_N));

练习

为新建文件菜单项添加快捷键Ctrl+N, 为打开文菜单项添加快捷键Ctrl+O

答案

cpp 复制代码
//设置快捷键 ctrl + n
new_action->setShortcut(QKeySequence(Qt::CTRL+Qt::Key_N));
//设置快捷键 ctrl + o
open_action->setShortcut(QKeySequence(Qt::CTRL+Qt::Key_O));
菜单项添加触发槽函数

当菜单项被选中或者按下快捷键触发时会执行相应的逻辑,比如新建项目被点击后,执行新建项目的操作。

点击菜单项会触发菜单项发出triggered信号

cpp 复制代码
[signal] void QAction::triggered(bool checked = false)

我们可以在MainWindow写一个槽函数,接受这个信号,并简单的弹出一个提示框做提示

QMessageBox

Qt 提示框的类为QMessageBox,QMessageBox提供了几个不同类型的对话框

信息消息框

cpp 复制代码
QMessageBox::information(this, "Information", "This is an information message.");

警告消息框

cpp 复制代码
QMessageBox::warning(this, "Warning", "This is a warning message.");

错误消息框

cpp 复制代码
QMessageBox::critical(this, "Critical", "This is a critical error message.");

问题消息框

有时候提示框会提出问题,让用户选择确认还是取消,可以用问题消息框。

cpp 复制代码
QMessageBox::StandardButton reply;
reply = QMessageBox::question(this, "Question", "Do you want to continue?", QMessageBox::Yes | QMessageBox::No);
if (reply == QMessageBox::Yes) {
    // User clicked Yes
} else {
    // User clicked No
}

练习

为新建文件或项目这个菜单项添加点击后弹出信息消息框,提示"点击了创建文件或项目"

答案

MainWindow中添加槽函数

cpp 复制代码
void MainWindow::slotNewFile()
{
    QMessageBox::information(this,"通知","点击了新建文件或项目菜单");
}

在MainWindow的构造函数中连接新建菜单项和槽函数

cpp 复制代码
//连接新建项目的菜单项的信号和mainwindow槽函数
connect(new_action, &QAction::triggered,this, &MainWindow::slotNewFile);
工具栏

添加工具栏

工具栏和菜单栏类似,如果ui文件中没有工具栏,我们可以用ui文件中的工具栏添加工具项。

否则我们需要先创建工具栏

cpp 复制代码
//创建工具栏
auto tool_bar = new QToolBar(this);
//主窗口添加工具栏
this->addToolBar(tool_bar);

添加工具项

工具项和菜单项一样,都是QAction类型所以添加工具项很简单

添加工具项

cpp 复制代码
//创建工具项
auto tool_new = new QAction(QIcon(":/res/new.png"),"新建",this);
auto tool_open = new QAction(QIcon(":/res/open.png"),"打开",this);
//添加工具项
tool_bar->addAction(tool_new);
tool_bar->addAction(tool_open);
//添加分割符号
tool_bar->addSeparator();
auto tool_exit = new QAction("退出",this);
//添加退出工具项
tool_bar->addAction(tool_exit);
状态栏

如果主窗口的ui里没有状态栏,需要创建。和之前菜单栏,工具栏类似,创建好状态栏再设置到主窗口中。

cpp 复制代码
    //创建状态栏
    QStatusBar *status = new QStatusBar(this);
    status->setObjectName("状态栏");
    //设置不显示label的边框
    status->setStyleSheet("QStatusBar::item{border: 0px}");
    //主窗口添加状态栏
    this->setStatusBar(status);

样式表也可以在代码中设置,我们之前是通过ui设置的。

状态栏可以设置标签,

cpp 复制代码
//创建标签
QLabel *statusLabel = new QLabel("我是状态栏", this);

//状态栏添加信息
//显示在左侧,并且3秒后自动消失
status->showMessage("我在3秒后会消失", 3000);
//添加右侧标签(永久性)
status->addPermanentWidget(statusLabel);

练习

练习实现状态栏

组件划分

按照Qt Designer中提供的不同功能分区,组件大体包括

  • 按钮类
    • QPushButton
    • QToolButton
    • QRadioButton
    • QCheckBox
  • 输入类
    • QLineEdit
    • QTextEdit
    • QPlainTextEdit
    • QDateEdit
    • QTimeEdit
    • QSPinBox
    • QComboBox
  • 显示类
    • QLabel
    • QGraphicsView
    • QProgressBar
  • 容器类
    • QWidget
    • QScrollArea
    • QFrame
    • QListWidget
    • QTableWidget
    • QTreeWidget

大家可以在Designer中拖动上述组件感受下都是什么,因为QT组件过于庞杂,接下来按照分类挑选常用的介绍

按钮类

QPushButton

QPushButton是Qt提供的基础按钮类,可以设置按钮的文本,图标,快捷键等。

QPUshButton的三个构造函数

cpp 复制代码
//一个参数指定父节点
QPushButton(QWidget *parent = nullptr);
//指定显示文本和父节点
QPushButton(const QString &text, QWidget *parent = nullptr);
//指定图标,显示文本,以及父节点
QPushButton(const QIcon &icon, const QString &text, QWidget *parent = nullptr);

我们通过代码的方式创建QPushButton并且显示在MainWindow上, 在MainWindow的构造函数里添加

cpp 复制代码
//创建按钮,显示文本
QPushButton *button = new QPushButton("Click Me", this);
//为按钮设置图标
button->setIcon(QIcon(":/res/open.png"));
//设置按钮的位置和大小
button->setGeometry(100, 100, 100, 40);

setGeometry四个参数分别为按钮所在横坐标,按钮所在纵坐标,按钮宽度,按钮的高度等。

运行后可显示按钮

按钮被点击后会发出clicked信号

cpp 复制代码
void  clicked(bool checked = false)

练习

我们可以在MainWindow写一个槽函数slotBtnClick,捕获这个信号,然后弹出消息框显示"按钮被点击"

答案

为MainWindow类添加槽函数

cpp 复制代码
void MainWindow::slotBtnClick()
{
    QMessageBox::information(this,"通知","点击了按钮");
}

在MainWindow构造函数中连接按钮点击信号和MainWindow槽函数

cpp 复制代码
connect(button, &QPushButton::clicked,this, &MainWindow::slotBtnClick);
QToolButton

QToolButton 是 Qt 框架中用于创建工具按钮的类。工具按钮通常用于工具栏或其他需要紧凑按钮布局的地方。与标准的 QPushButton 不同,QToolButton 通常更小,并且可以只显示图标、只显示文本或同时显示图标和文本。 使用时需包含QToolButton头文件

QToolButton的构造函数仅有一个参数

cpp 复制代码
QToolButton(QWidget *parent = nullptr)

QToolButton同样支持设置现实的图标和文本

cpp 复制代码
//创建一个工具按钮
QToolButton *toolButton = new QToolButton(this);
//设置图标
toolButton->setIcon(QIcon(":/res/new.png"));
//设置文本
toolButton->setText("Tool");

工具按钮可以设置几种显示样式

cpp 复制代码
// 仅显示图标
toolButton->setToolButtonStyle(Qt::ToolButtonIconOnly); 
 // 仅显示文本
toolButton->setToolButtonStyle(Qt::ToolButtonTextOnly);
// 图标在文本旁边
toolButton->setToolButtonStyle(Qt::ToolButtonTextBesideIcon); 
// 图标在文本上方
toolButton->setToolButtonStyle(Qt::ToolButtonTextUnderIcon);  

工具按钮可以放在工具栏里

cpp 复制代码
//创建一个工具按钮
QToolButton *toolButton = new QToolButton(this);
//设置图标
toolButton->setIcon(QIcon(":/res/new.png"));
//设置文本
toolButton->setText("Tool");
 //设置按钮样式,文本在图标旁边
 toolButton->setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
//工具栏添加按钮
tool_bar->addWidget(toolButton);

QToolButton按钮被点击后也会发出clicked信号

练习

创建一个QToolButton,放在工具栏里,按钮样式为Qt::ToolButtonTextBesideIcon。

点击按钮后,弹出消息框显示"ToolButton被点击了"

答案

MainWindow构造函数里添加

cpp 复制代码
//创建一个工具按钮
QToolButton *toolButton = new QToolButton(this);
//设置图标
toolButton->setIcon(QIcon(":/res/new.png"));
//设置文本
toolButton->setText("Tool");
//设置按钮样式,文本在图标旁边
toolButton->setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
//按钮添加到工具栏上
tool_bar->addWidget(toolButton);

//连接按钮的点击信号
connect(toolButton,&QToolButton::clicked,this, &MainWindow::slotToolBtnClick);

MainWindow添加槽函数

cpp 复制代码
void MainWindow::slotToolBtnClick()
{
    QMessageBox::information(this,"通知","点击了工具按钮");
}
QRadioButton

QRadioButton为单选按钮,后续我们通过例子来演示和学习。这里大家可以拖动Designer中的QRadioButton到MainWindow.ui中,看看QRadioButton的样子

QCheckBox

QCheckBox为多选框, 大家可以添加到ui,启动程序看看样式

输入类控件

QLineEdit

QLineEdit主要是用来单行输入的控件,大家可以将一个QLineEdit拖动到ui里, 运行后看看效果

QLineEdit有几个信号介绍一下

cpp 复制代码
//光标位置变化后发送信号
void  cursorPositionChanged(int oldPos, int newPos)
//编辑完成后发送,失去光标时发送
void  editingFinished()
//输入被拒绝时发出这个信号
void  inputRejected()
//按下回车键后
void  returnPressed()
//选择区域变化后
void  selectionChanged()
//文本变化后
void  textChanged(const QString &text)
//文本被编辑
void  textEdited(const QString &text)

这些信号不用死记硬背,用到的时候查下assistant手册或者AI都可以,会用就行

QLineEdit也支持设置输入的模式

Normal 就是输入的内容正常显示

NoEcho就是输入的内容完全不显示,输入什么都是一片空白

Password就是以密码点的形式显示

PasswordEchoOnEdit就是输入的时候显示字符,失去焦点后变成密码点

在输入时是这样

失去焦点

通过setEchoMode可以设置输入模式

cpp 复制代码
void setEchoMode(QLineEdit::EchoMode)

我们做个练习看看效果

练习

MainWindow上添加一个QLineEdit,设置输入模式为Password. 当输入完成后打印输入的密码

答案

mainwindow的构造函数里添加

cpp 复制代码
//设置为密码输入模式
ui->lineEdit->setEchoMode(QLineEdit::Password);
//连接失去焦点信号和槽函数
connect(ui->lineEdit, &QLineEdit::editingFinished, [this](){
    qDebug() << "editing Finished slot";
});

//连接按下回车信号和槽函数
connect(ui->lineEdit, &QLineEdit::returnPressed, [this](){
    qDebug() << "returnPressed slot";
});
QTextEdit

文本编辑器,和QLineEdit一样,都是输入控件,QTextEdit支持多行输入。

QTextPlainEdit

QTextPlainEdit为纯文本编辑器,和QTextEdit功能类似,不做赘述

QDateEdit

QDateEdit是编辑日期的控件,拖动到ui运行可查看到

QDateEdit支持设置日期

cpp 复制代码
QDateEdit *dateEdit = new QDateEdit(this);
dateEdit->setDate(QDate::currentDate());  // 设置为当前日期

获取日期

cpp 复制代码
QDate selectedDate = dateEdit->date();
qDebug() << "Selected date:" << selectedDate.toString();

设置日期展示样式

cpp 复制代码
dateEdit->setDisplayFormat("yyyy-MM-dd");

信号和槽

QDateEdit 提供了一些信号,例如 dateChanged 信号,当日期发生变化时会发出该信号。可以连接到槽函数来处理日期变化事件:

cpp 复制代码
//连接日期变化信号
connect(dateEdit, &QDateEdit::dateChanged, this, &MainWindow::onDateChanged);
//日期变化的槽函数
void MainWindow::onDateChanged(const QDate &date) {
    qDebug() << "New date selected:" << date.toString();
}
QTimeEdit

QTimeEdit和QDateEdit用法类似

QSpinBox

QSpinBox 是 Qt 框架中的一个控件,用于显示和编辑整数值。它提供了一个带有上下按钮的输入框,用户可以通过点击按钮或直接输入来更改数值。以下是 QSpinBox 的常见用法和示例。

基本用法

创建一个 QSpinBox 控件

cpp 复制代码
QSpinBox *spinBox = new QSpinBox(this);

设置初始值

可以使用 setValue 方法来设置 QSpinBox 的初始值:

cpp 复制代码
spinBox->setValue(10);

获取当前值

可以使用 value 方法来获取当前的数值:

cpp 复制代码
int currentValue = spinBox->value();
qDebug() << "Current value:" << currentValue;

设置数值范围

可以使用 setMinimumsetMaximum 方法来设置允许的数值范围:

cpp 复制代码
spinBox->setMinimum(0);  // 最小值为0
spinBox->setMaximum(100); // 最大值为100

或者,使用 setRange 方法同时设置最小值和最大值:

cpp 复制代码
spinBox->setRange(0, 100);

设置步长

可以使用 setSingleStep 方法来设置每次点击上下按钮时数值的变化步长:

cpp 复制代码
spinBox->setSingleStep(5);  // 每次增加或减少5

设置前缀和后缀

可以使用 setPrefixsetSuffix 方法来设置显示在数值前后的文本:

cpp 复制代码
spinBox->setPrefix("$");  // 在数值前显示美元符号
spinBox->setSuffix(" kg"); // 在数值后显示单位

信号和槽

QSpinBox 提供了一些信号,例如 valueChanged 信号,当数值发生变化时会发出该信号。可以连接到槽函数来处理数值变化事件:

cpp 复制代码
connect(spinBox, SIGNAL(valueChanged(int)), this, SLOT(onValueChanged(int)));

void MainWindow::onValueChanged(int value) {
    qDebug() << "New value:" << value;
}

练习

把上面的例子串起来写一写

cpp 复制代码
QSpinBox *spinBox = new QSpinBox(this);
       spinBox->setRange(0, 100);
       spinBox->setValue(10);
       spinBox->setSingleStep(5);
       spinBox->setPrefix("$");
       spinBox->setSuffix(" kg");

spinBox->setGeometry(250,300,70,30);

总结

QSpinBox 是一个功能强大的控件,用于显示和编辑整数值。通过设置初始值、数值范围、步长、前缀和后缀等,可以灵活地定制 QSpinBox 的行为。结合信号和槽机制,可以轻松处理数值变化事件。这个控件在需要数值输入的应用程序中非常有用。

QComboBox

QComboBox 是 Qt 提供的一个下拉列表控件,允许用户从一个列表中选择一个条目。它可以包含文本条目,也可以包含更复杂的自定义项。

添加条目的接口

cpp 复制代码
void  addItem(const QString &text, const QVariant &userData = QVariant())
void  addItem(const QIcon &icon, const QString &text, const QVariant &userData = QVariant())

userData字段很少用到,在传递自定义数据的时候会用到。我们添加条目时默认只写一个文本参数即可。

练习

创建并添加条目

cpp 复制代码
//创建下拉列表控件
QComboBox *comboBox = new QComboBox(this);
//添加条目
comboBox->addItem("Option 1");
comboBox->addItem("Option 2");
comboBox->addItem("Option 3");
//移动到250,400位置
comboBox->move(250,400);

显示类

QLabel

QLabel 是 Qt 提供的用于显示文本或图像。它常用于展示静态内容,并且可以与其他控件组合使用来构建用户界面。

可以直接在构造函数里指定QLabel要显示的文本

cpp 复制代码
explicit QLabel(QWidget *parent=nullptr, Qt::WindowFlags f=Qt::WindowFlags());
explicit QLabel(const QString &text, QWidget *parent=nullptr, Qt::WindowFlags f=Qt::WindowFlags());

例如:

cpp 复制代码
 // 创建一个简单的文本标签
 QLabel *textLabel = new QLabel("Hello, QLabel!");

指定父窗口后,QLabel会自动添加到父窗口的(0,0)位置,可以通过move移动到指定的位置

cpp 复制代码
 QLabel *textLabel = new QLabel("Hello, QLabel!",this);

如果未设置父窗口,可调用addWidget将label加入指定窗口. 比如在MainWindow的构造函数中调用

cpp 复制代码
this->addWidget(textLabel);

也可以通过setText更新QLabel显示的文本

cpp 复制代码
textLabel->setText("Hello, Heima");

练习

主窗口设置一个下拉列表框和QLabel,下拉列表框有三个下拉选项(option1, option2, option3),

选择下拉条目后,label显示下拉列表框选择的内容.

提示:

QComboBox在条目有变化的时候会发出信号 currentTextChanged

答案

cpp 复制代码
//创建下拉列表控件
QComboBox *comboBox = new QComboBox(this);
//添加条目
comboBox->addItem("Option 1");
comboBox->addItem("Option 2");
comboBox->addItem("Option 3");
//移动到250,400位置
comboBox->move(250,400);

//获取当前下拉框文本
auto text = comboBox->currentText();
QLabel *textLabel = new QLabel(this);
textLabel->move(250,500);
textLabel->setText(text);
//连接下拉框文本变化的信号
connect(comboBox,&QComboBox::currentTextChanged, [textLabel,comboBox](){
    textLabel->setText(comboBox->currentText());
});
QGraphicsView

QGraphicsView 是 Qt 框架中的一个类,用于显示和交互 QGraphicsScene 中的内容。它是 Qt 的图形视图框架的一部分,该框架提供了一种灵活且高效的方法来管理和显示复杂的 2D 图形.QGraphicsView 提供了一个视口(viewport),通过这个视口可以查看 QGraphicsScene 的一部分。视口可以移动和缩放,从而查看场景的不同部分。之后在绘图的时候给大家演示,这个目前仅作了解

QProgressBar

QProgressBar 是 Qt 框架中的一个小部件类,用于显示任务进度的图形化表示。它通常用于展示任务的完成百分比,给用户提供任务进度的视觉反馈。QProgressBar 的使用非常简单且直观,适用于各种需要显示进度的场景,例如文件下载、数据处理等

设置范围

可以通过 setRange(int minimum, int maximum) 方法设置进度条的最小值和最大值。默认情况下,最小值为 0,最大值为 100。

设置当前值

可以通过 setValue(int value) 方法设置当前的进度值。进度值在最小值和最大值之间变化。

文本显示

QProgressBar 可以在进度条上显示文本,例如完成百分比。可以通过 setFormat(const QString &format) 方法自定义显示的文本格式。

练习

主界面拖动一个按钮和进度条。进度条初始值为0,范围为0到100.

当点击按钮后,定时更新进度条,每100ms进度条的数值+1。进度条满后停止计时。

提示:QTimer为定时器类,大家锻炼下查阅assistant的能力

QTimer有start函数开启定时器,参数为设置的检测时间间隔,单位为ms

QTimer信号timout会在每次时间间隔达到时发送。

QTimer有stop函数停止定时器

答案

ui中拖动按钮和进度条,按钮名称修改为timerBtn, 进度条修改为timerProgress

cpp 复制代码
//定义定时器
auto timer = new QTimer(this);
// 绑定定时器检测间隔超时信号和回调函数
connect(timer, &QTimer::timeout, [this, timer](){
    //判断进度条是否满格
    if(ui->timerProgress->value() >= 100){
        timer->stop();
        return;
    }
    //更新进度条数值
    ui->timerProgress->setValue(ui->timerProgress->value()+1);
});

//连接点击信号
connect(ui->timerBtn,&QPushButton::clicked,[this,timer](){
    //开始定时器,每个100ms进行检测一次
    timer->start(100);
});

还有一些组件比如Slider,以后用到了再查文档即可,QT提供的控件库太丰富了,学习常用的先入手。

布局

当我们拖动一个新的控件到ui文件中,需要关注ui文件中其他控件的位置,防止两个控件重叠。

有时,随着界面调整,按照位置设置好的控件不会随着界面拉伸而改变。

比如我们拖动MainWindow界面,控件并没有随着MainWindow的拉伸做调整

对于这种情况,我们可以采用Layout布局解决。

布局分为四种,有垂直布局,网格布局,水平布局,表单布局。

我们先看水平布局, 布局中的所有控件水平排列

垂直布局, 布局中的所有控件垂直排列

网格布局,布局中的所有控件按照网格的方式排列,有的占据多行或者多列。

表单布局,可以方便的完成表单样式,比如我们一些登录注册信息ui可以用这个布局。

设置布局整体有三种方式:

  1. 在ui中选中窗口,将窗口调整为垂直布局,网格布局,或者水平布局的一种
  2. 拖动一种布局放入ui,再将其他控件放入布局中。
  3. 写代码添加布局,然后再写代码将控件加入布局中。

先介绍第一种,我们双击mainwindow.ui,打开QT designer , 选中右侧对象层级表中centralWidget,

再点击工具栏中网格布局图标

将MainWindow的centralwidget设置为网格布局,可以在ui布局中看到控件整体布局变成了网格模式

运行起来,仍有部分控件散乱排布,是因为我们没有将控件加入布局,直接添加到mainwindow导致的,接下来我们用代码的方式将这些控件加入布局.

因为我们将centralwidget修改为网格布局,所以ui->centralWidget->layout()可以直接访问这个网格布局

cpp 复制代码
    //创建按钮,显示文本
    QPushButton *button = new QPushButton("Click Me", this);
    //为按钮设置图标
    button->setIcon(QIcon(":/res/open.png"));
    //设置按钮的位置和大小
    button->setGeometry(100, 100, 100, 40);
    connect(button, &QPushButton::clicked,
            this, &MainWindow::slotBtnClick);
    ui->centralWidget->layout()->addWidget(button);

依次类推,大家可以将其他的控件都加入布局,看到i的效果就是

当我们缩放或者拉伸,可以看到控件会随着拉伸变化。

我们在对象管理器中选中centralWidget,观察右下方属性管理器

红色框中 layoutHorizontalSpacing表示控件之间的水平间距

layoutVerticalSpacing表示控件之间的垂直间距

layoutRowStretch表示垂直拉伸比例,当布局被拉伸后,里面的控件垂直拉伸的比例如何。

layoutColumnStretch表示水平拉伸比例,当布局被拉伸后,里面的控件水平拉伸的比例如何。

如果是水平布局或i这垂直布局,间距用layoutSpacing表示,拉伸比用layoutStretch表示。

代码方式创建布局

布局类型:

  • 水平布局QHBoxLayout
  • 垂直布局QVBoxLayout
  • 网格布局QGridLayout

向布局中添加widget控件,第一个参数是要添加的控件,第二个参数是该控件的拉伸比例,不设置默认等比拉伸

cpp 复制代码
void addWidget(QWidget *, int stretch = 0, Qt::Alignment alignment = Qt::Alignment());

假设水平布局中有两个控件A和B,A的拉伸比例为2,B的拉伸比例为1,那么当界面被水平拉伸时,控件A宽度的增长速度是B的2倍

拉伸后

可以看到拉伸后A的宽度是B的2倍

练习

我们创建水平布局,封装到函数SetHorizontalLayout中

cpp 复制代码
void MainWindow::SetHorizontalLayout()
{
    //添加水平布局
    auto layout = new QHBoxLayout(this);
    //创建两个按钮
    auto btn1 = new QPushButton("btn1",this);
    auto btn2 = new QPushButton("btn2",this);
    //将按钮加入到layout中
    layout->addWidget(btn1);
    layout->addWidget(btn2);
    //将centralwidget布局设置为水平布局
    ui->centralWidget->setLayout(layout);
}

在MainWindow的构造函数中调用,再启动程序能看到按钮并排排列了。

创建垂直布局

cpp 复制代码
void MainWindow::SetVerticalLayout()
{
    //添加垂直布局
    auto layout = new QVBoxLayout(this);
    //添加两个按钮
    auto btn1 = new QPushButton("btn1",this);
    auto btn2 = new QPushButton("btn2",this);
    //将按钮加入布局
    layout->addWidget(btn1);
    layout->addWidget(btn2);
    //将centralwidget布局设置为垂直布局
    ui->centralWidget->setLayout(layout);
}

创建网格布局

cpp 复制代码
void MainWindow::SetGridLayout()
{
    //添加网格布局
    auto layout = new QGridLayout(this);
    //创建几个按钮
    auto btn1 = new QPushButton("btn1",this);
    auto btn2 = new QPushButton("btn2", this);
    auto btn3 = new QPushButton("btn3", this);
    auto btn4 = new QPushButton("btn4", this);
    auto btn5 = new QPushButton("btn5", this);
    //btn1 放在第一行第一列,占一行一列
    layout->addWidget(btn1,0,0,1,1);
    //btn2 放在第二行第一列,占一行两列
    layout->addWidget(btn2,1,0,1,2);
    //btn3 放在第二行第三列,占一行一列
    layout->addWidget(btn3,1,2,1,1);
    //btn4 放在第三行第一列,占两行一列
    layout->addWidget(btn4,2,0,2,1);
    //btn5 放在第四行第二列,占一行一列
    layout->addWidget(btn5,3,1,1,1);
    //将centralwidget设置为网格布局
    this->centralWidget()->setLayout(layout);
}

因为整个页面高度很大,所以按钮布局看起来高度不一致。可以拉伸页面,将高度缩小为最小,就能看到btn4实际是占用了两行。

添加弹簧

QT提供了弹簧控件,可以通过Designer拖动到ui中,Horizontal Spacer是水平弹簧,Vertical Spacer是垂直弹簧

弹簧的作用就是压缩空间,让控件达到紧凑排布的效果。

也可写代码创建,写代码创建的弹簧是不分垂直还是水平的,取决于将弹簧添加到什么布局里,将弹簧加到水平布局里就是水平弹簧,将弹簧加到垂直布局里就是垂直布局

QSpacerItem构造函数

cpp 复制代码
QSpacerItem(int w, int h,QSizePolicy::Policy hData = QSizePolicy::Minimum,
                 QSizePolicy::Policy vData = QSizePolicy::Minimum)

第一个参数为弹簧的宽,第二个参数为弹簧的高,第三个参数为弹簧的水平策略,第四个参数为弹簧的垂直策略。

常见的 QSizePolicy策略

  1. Fixed :
    小部件的大小是固定的,不能扩展或收缩。
  2. Minimum :
    小部件可以收缩到最小大小,但不能扩展。
  3. Maximum :
    小部件可以扩展到最大大小,但不能收缩。
  4. Preferred :
    小部件可以根据其建议的大小进行调整,但不会强制扩展或收缩。
  5. Expanding :
    小部件可以扩展以填充可用空间。
  6. MinimumExpanding :
    小部件可以收缩到最小大小,但也可以扩展以填充可用空间。
  7. Ignored :
    小部件的大小策略被忽略,布局管理器将不会考虑它的大小。

不用死记硬背,最常用的就是好Expanding和Fixed,其余用到了再查文档。

将弹簧加入布局的函数为

cpp 复制代码
void addSpacerItem(QSpacerItem *spacerItem);

练习

写代码在水平布局中插入一个弹簧,将按钮挤压到最左侧。

cpp 复制代码
void MainWindow::SetHorizontalLayout()
{
    //添加水平布局
    auto layout = new QHBoxLayout(this);
    //创建两个按钮
    auto btn1 = new QPushButton("btn1",this);
    auto btn2 = new QPushButton("btn2",this);
    //将按钮加入到layout中
    layout->addWidget(btn1);
    layout->addWidget(btn2);
    //创建水平弹簧,水平为扩展策略,垂直为可扩充到最大20像素
    auto h_spacer = new QSpacerItem(40,20,
         QSizePolicy::Expanding,QSizePolicy::Maximum);
    //布局里添加弹簧
    layout->addSpacerItem(h_spacer);
    //将centralwidget布局设置为水平布局
    ui->centralWidget->setLayout(layout);
}

效果

垂直布局也是这么设置,添加的弹簧默认为垂直弹簧。

那么网格布局添加弹簧需要指定弹簧所在的行列,添加的函数变成了addItem

cpp 复制代码
void addItem(QLayoutItem *item, int row, int column, int rowSpan = 1, 
             int columnSpan = 1, Qt::Alignment = Qt::Alignment());

我们基于前面创建的网格布局代码,添加弹簧

cpp 复制代码
//创建垂直弹簧,水平策略为Maximum,垂直方向为Expanding
auto v_spacer = new QSpacerItem(40,20,
        QSizePolicy::Maximum,QSizePolicy::Expanding);
//创建水平弹簧,水平策略为Expanding,垂直策略为Maximum
auto h_spacer = new QSpacerItem(40,20,
        QSizePolicy::Expanding, QSizePolicy::Maximum);
//加入垂直弹簧,放在第五行第1列
layout->addItem(v_spacer,4,0);
//加入水平弹簧,放在第四行第3列
layout->addItem(h_spacer,3,2);
//将centralwidget设置为网格布局
this->centralWidget()->setLayout(layout);

效果

布局边界

我们将一个控件或者多个控件放入布局后,它们与布局边界之间的距离叫做边界(Margin)

可通过Designer中对布局设置编剧

也可以通过代码设置

cpp 复制代码
//设置边距
void setContentsMargins(int left, int top, int right, int bottom);

练习

将之前的水平布局边距分别设置为左边距20,上边距30,右边距40,底边距50的样式

答案

cpp 复制代码
layout->setContentsMargins(20,30,40,50);

QListWidget

QListWidget 是 Qt 提供的一个方便的列表小部件

我们打开ui布局管理器,拖动一个QListWidget放入mainwindow.ui中

右键这个QListWidget,选择编辑项目

点击加号创建项目,项目名字可以修改

保存ui运行一下,看看效果

综合练习

实现如下界面,Profession下拉列表可以用QListWidget

相关推荐
森G4 小时前
21、信号和槽详解---------QT基础
qt
西装没钱买4 小时前
QT组播的建立和使用(绑定特定的网卡,绑定特定IP)
网络·c++·qt·udp·udp组播
森G5 小时前
20、元对象系统---------QT基础
qt
Laurence5 小时前
CMake 报错 Failed to find required Qt component WebEngineWidgets
qt·webengine·cmake·找不到
习惯就好zz5 小时前
Qt Quick 系统托盘完整实践
开发语言·qt·qml·系统托盘·system tray·qapplication·qguiapplication
笨笨马甲5 小时前
Qt集成OpenCV
开发语言·qt
笨笨马甲5 小时前
Qt 工业机器视觉开发
开发语言·qt
小灰灰搞电子6 小时前
Qt 打印输出:printf与qDebug的区别
开发语言·qt
火山上的企鹅6 小时前
Qt/QGroundControl 实战:接入 Skydroid(云卓) G20 遥控器 Android SDK 并实时显示摇杆与信号质量
android·开发语言·qt·qgroundcontrol·云卓sdk