Qt5 小部件 II
最后修改于 2023 年 10 月 18 日
在本 Qt5 C++ 编程教程中,我们将继续讨论 Qt5 小部件。我们涵盖以下小部件:QCheckBox
、QListWidget
、QProgressBar
、QPixmap
、QSplitter
和 QTableWidget
。
QCheckBox
QCheckBox
是一个具有两种状态的小部件:开启和关闭。它是一个带有标签的框。如果选中复选框,则由框中的一个勾号表示。
在我们的示例中,我们在窗口上显示一个复选框。如果选中复选框,则显示窗口的标题。否则,它将被隐藏。
#pragma once #include <QWidget> class CheckBox : public QWidget { Q_OBJECT public: CheckBox(QWidget *parent = 0); private slots: void showTitle(int); };
这是我们代码示例的头文件。
#include <QCheckBox> #include <QHBoxLayout> #include "checkbox.h" CheckBox::CheckBox(QWidget *parent) : QWidget(parent) { QHBoxLayout *hbox = new QHBoxLayout(this); QCheckBox *cb = new QCheckBox("Show Title", this); cb->setCheckState(Qt::Checked); hbox->addWidget(cb, 0, Qt::AlignLeft | Qt::AlignTop); connect(cb, &QCheckBox::stateChanged, this, &CheckBox::showTitle); } void CheckBox::showTitle(int state) { if (state == Qt::Checked) { setWindowTitle("QCheckBox"); } else { setWindowTitle(" "); } }
我们在窗口上显示一个复选框,并将其连接到 showTitle
槽。
cb->setCheckState(Qt::Checked);
该复选框在示例开始时被选中。
void CheckBox::showTitle(int state) { if (state == Qt::Checked) { setWindowTitle("QCheckBox"); } else { setWindowTitle(" "); } }
我们确定复选框的状态,并相应地调用 setWindowTitle
。
#include <QApplication> #include "checkbox.h" int main(int argc, char *argv[]) { QApplication app(argc, argv); CheckBox window; window.resize(250, 150); window.setWindowTitle("QCheckBox"); window.show(); return app.exec(); }
这是主文件。

QListWidget
QListWidget
是一个用于显示项目列表的小部件。在我们的示例中,我们演示了如何从列表小部件添加、重命名和删除项目。
#pragma once #include <QWidget> #include <QPushButton> #include <QListWidget> class ListWidget : public QWidget { Q_OBJECT public: ListWidget(QWidget *parent = 0); private slots: void addItem(); void renameItem(); void removeItem(); void clearItems(); private: QListWidget *lw; QPushButton *add; QPushButton *rename; QPushButton *remove; QPushButton *removeAll; };
该示例的头文件。
#include "listwidget.h" #include <QVBoxLayout> #include <QInputDialog> ListWidget::ListWidget(QWidget *parent) : QWidget(parent) { QVBoxLayout *vbox = new QVBoxLayout(); vbox->setSpacing(10); QHBoxLayout *hbox = new QHBoxLayout(this); lw = new QListWidget(this); lw->addItem("The Omen"); lw->addItem("The Exorcist"); lw->addItem("Notes on a scandal"); lw->addItem("Fargo"); lw->addItem("Capote"); add = new QPushButton("Add", this); rename = new QPushButton("Rename", this); remove = new QPushButton("Remove", this); removeAll = new QPushButton("Remove All", this); vbox->setSpacing(3); vbox->addStretch(1); vbox->addWidget(add); vbox->addWidget(rename); vbox->addWidget(remove); vbox->addWidget(removeAll); vbox->addStretch(1); hbox->addWidget(lw); hbox->addSpacing(15); hbox->addLayout(vbox); connect(add, &QPushButton::clicked, this, &ListWidget::addItem); connect(rename, &QPushButton::clicked, this, &ListWidget::renameItem); connect(remove, &QPushButton::clicked, this, &ListWidget::removeItem); connect(removeAll, &QPushButton::clicked, this, &ListWidget::clearItems); setLayout(hbox); } void ListWidget::addItem() { QString c_text = QInputDialog::getText(this, "Item", "Enter new item"); QString s_text = c_text.simplified(); if (!s_text.isEmpty()) { lw->addItem(s_text); int r = lw->count() - 1; lw->setCurrentRow(r); } } void ListWidget::renameItem() { QListWidgetItem *curitem = lw->currentItem(); int r = lw->row(curitem); QString c_text = curitem->text(); QString r_text = QInputDialog::getText(this, "Item", "Enter new item", QLineEdit::Normal, c_text); QString s_text = r_text.simplified(); if (!s_text.isEmpty()) { QListWidgetItem *item = lw->takeItem(r); delete item; lw->insertItem(r, s_text); lw->setCurrentRow(r); } } void ListWidget::removeItem() { int r = lw->currentRow(); if (r != -1) { QListWidgetItem *item = lw->takeItem(r); delete item; } } void ListWidget::clearItems(){ if (lw->count() != 0) { lw->clear(); } }
我们显示一个列表小部件和四个按钮。我们使用这些按钮从列表小部件添加、重命名和删除项目。
lw = new QListWidget(this); lw->addItem("The Omen"); lw->addItem("The Exorcist"); lw->addItem("Notes on a scandal"); lw->addItem("Fargo"); lw->addItem("Capote);
创建 QListWidget
并用五个项目填充它。
void ListWidget::addItem() { QString c_text = QInputDialog::getText(this, "Item", "Enter new item"); QString s_text = c_text.simplified(); if (!s_text.isEmpty()) { lw->addItem(s_text); int r = lw->count() - 1; lw->setCurrentRow(r); } }
addItem
方法将一个新项目添加到列表小部件。该方法弹出一个输入对话框。该对话框返回一个字符串值。我们使用 simplified
方法从字符串中删除可能的空格。如果返回的字符串不为空,我们将其添加到列表小部件的末尾。最后,我们使用 setCurrentRow
方法突出显示当前插入的项目。
void ListWidget::renameItem() { QListWidgetItem *curitem = lw->currentItem(); int r = lw->row(curitem); QString c_text = curitem->text(); QString r_text = QInputDialog::getText(this, "Item", "Enter new item", QLineEdit::Normal, c_text); QString s_text = r_text.simplified(); if (!s_text.isEmpty()) { QListWidgetItem *item = lw->takeItem(r); delete item; lw->insertItem(r, s_text); lw->setCurrentRow(r); } }
重命名一个项目包括几个步骤。首先,我们使用 currentItem
方法获取当前项目。我们获取项目的文本和项目所在行。项目的文本显示在 QInputDialog
对话框中。从对话框返回的字符串由 simplified
方法处理,以删除潜在的空格。然后我们使用 takeItem
方法删除旧项目,并用 insertItem
方法替换它。我们删除 takeItem
方法删除的项目,因为删除的项目不再由 Qt 管理。最后,setCurrentRow
选择新项目。
void ListWidget::removeItem() { int r = lw->currentRow(); if (r != -1) { QListWidgetItem *item = lw->takeItem(r); delete item; } }
removeItem
从列表中删除一个特定项目。首先,我们使用 currentRow
方法获取当前选定的行。(如果没有剩余行,则返回 -1。)当前选定的项目使用 takeItem
方法删除。
void ListWidget::clearItems(){ if (lw->count() != 0) { lw->clear(); } }
clear
方法从列表小部件中删除所有项目。
#include <QApplication> #include "listwidget.h" int main(int argc, char *argv[]) { QApplication app(argc, argv); ListWidget window; window.setWindowTitle("QListWidget"); window.show(); return app.exec(); }
这是主文件。

QProgressBar
QProgressBar
用于向用户指示操作的进度。
#pragma once #include <QWidget> #include <QProgressBar> #include <QPushButton> class ProgressBarEx : public QWidget { Q_OBJECT public: ProgressBarEx(QWidget *parent = 0); private: int progress; QTimer *timer; QProgressBar *pbar; QPushButton *startBtn; QPushButton *stopBtn; static const int DELAY = 200; static const int MAX_VALUE = 100; void updateBar(); void startMyTimer(); void stopMyTimer(); };
该示例的头文件。
#include <QProgressBar> #include <QTimer> #include <QGridLayout> #include "progressbar.h" ProgressBarEx::ProgressBarEx(QWidget *parent) : QWidget(parent) { progress = 0; timer = new QTimer(this); connect(timer, &QTimer::timeout, this, &ProgressBarEx::updateBar); QGridLayout *grid = new QGridLayout(this); grid->setColumnStretch(2, 1); pbar = new QProgressBar(); grid->addWidget(pbar, 0, 0, 1, 3); startBtn = new QPushButton("Start", this); connect(startBtn, &QPushButton::clicked, this, &ProgressBarEx::startMyTimer); grid->addWidget(startBtn, 1, 0, 1, 1); stopBtn = new QPushButton("Stop", this); connect(stopBtn, &QPushButton::clicked, this, &ProgressBarEx::stopMyTimer); grid->addWidget(stopBtn, 1, 1); } void ProgressBarEx::startMyTimer() { if (progress >= MAX_VALUE) { progress = 0; pbar->setValue(0); } if (!timer->isActive()) { startBtn->setEnabled(false); stopBtn->setEnabled(true); timer->start(DELAY); } } void ProgressBarEx::stopMyTimer() { if (timer->isActive()) { startBtn->setEnabled(true); stopBtn->setEnabled(false); timer->stop(); } } void ProgressBarEx::updateBar() { progress++; if (progress <= MAX_VALUE) { pbar->setValue(progress); } else { timer->stop(); startBtn->setEnabled(true); stopBtn->setEnabled(false); } }
在示例中,我们有一个 QProgressBar
和两个按钮。一个按钮启动计时器,计时器又更新进度条。另一个按钮停止计时器。
timer = new QTimer(this); connect(timer, &QTimer::timeout, this, &ProgressBarEx::updateBar);
QTimer
用于控制 QProgressBar
小部件。
pbar = new QProgressBar();
创建 QProgressBar
的实例。默认的最小值和最大值分别为 0 和 100。
if (!timer->isActive()) { startBtn->setEnabled(false); stopBtn->setEnabled(true); timer->start(DELAY); }
根据进度条的状态,启用或禁用按钮。这是通过 setEnabled
方法完成的。
void ProgressBarEx::updateBar() { progress++; if (progress <= MAX_VALUE) { pbar->setValue(progress); } else { timer->stop(); startBtn->setEnabled(true); stopBtn->setEnabled(false); } }
进度存储在 progress
变量中。setValue
更新进度条的当前值。
#include <QApplication> #include "progressbar.h" int main(int argc, char *argv[]) { QApplication app(argc, argv); ProgressBarEx window; window.resize(250, 150); window.setWindowTitle("QProgressBar"); window.show(); return app.exec(); }
这是主文件。

QPixmap
QPixmap
是用于处理图像的小部件之一。它针对在屏幕上显示图像进行了优化。在我们的代码示例中,我们使用 QPixmap
在窗口上显示图像。
#pragma once #include <QWidget> class Pixmap : public QWidget { public: Pixmap(QWidget *parent = 0); };
该示例的头文件。
#include <QPixmap> #include <QLabel> #include <QHBoxLayout> #include "pixmap.h" Pixmap::Pixmap(QWidget *parent) : QWidget(parent) { QHBoxLayout *hbox = new QHBoxLayout(this); QPixmap pixmap("bojnice.jpg"); QLabel *label = new QLabel(this); label->setPixmap(pixmap); hbox->addWidget(label, 0, Qt::AlignTop); }
我们展示了一张位于斯洛伐克中部的著名城堡的图像。
QPixmap pixmap("bojnice.jpg"); QLabel *label = new QLabel(this); label->setPixmap(pixmap);
我们创建一个像素图并将其放入标签小部件中。
#include <QApplication> #include "pixmap.h" int main(int argc, char *argv[]) { QApplication app(argc, argv); Pixmap window; window.setWindowTitle("QPixmap"); window.show(); return app.exec(); }
这是主文件。
QSplitter
QSplitter
允许用户通过拖动子小部件之间的边界来控制子小部件的大小。在我们的示例中,我们展示了三个 QFrame
小部件,它们由两个分隔器组织。
#pragma once #include <QWidget> class Splitter : public QWidget { public: Splitter(QWidget *parent = 0); };
该示例的头文件。
#include <QFrame> #include <QSplitter> #include <QHBoxLayout> #include "splitter.h" Splitter::Splitter(QWidget *parent) : QWidget(parent) { QHBoxLayout *hbox = new QHBoxLayout(this); QFrame *topleft = new QFrame(this); topleft->setFrameShape(QFrame::StyledPanel); QFrame *topright = new QFrame(this); topright->setFrameShape(QFrame::StyledPanel); QSplitter *splitter1 = new QSplitter(Qt::Horizontal, this); splitter1->addWidget(topleft); splitter1->addWidget(topright); QFrame *bottom = new QFrame(this); bottom->setFrameShape(QFrame::StyledPanel); QSplitter *splitter2 = new QSplitter(Qt::Vertical, this); splitter2->addWidget(splitter1); splitter2->addWidget(bottom); QList<int> sizes({50, 100}); splitter2->setSizes(sizes); hbox->addWidget(splitter2); }
在示例中,我们有三个框架小部件和两个分隔器小部件。
QSplitter *splitter1 = new QSplitter(Qt::Horizontal, this); splitter1->addWidget(topleft); splitter1->addWidget(topright);
我们创建一个分隔器小部件,并将两个框架小部件添加到分隔器中。
QSplitter *splitter2 = new QSplitter(Qt::Vertical, this); splitter2->addWidget(splitter1);
我们还可以将一个拆分器添加到另一个拆分器窗口部件。
QList<int> sizes({50, 100}); splitter2->setSizes(sizes);
使用 setSizes
方法,我们为分隔器的子小部件设置大小。
#include <QDesktopWidget> #include <QApplication> #include "splitter.h" int main(int argc, char *argv[]) { QApplication app(argc, argv); Splitter window; window.resize(350, 300); window.setWindowTitle("QSplitter"); window.show(); return app.exec(); }
这是主文件。

在某些桌面主题中,分隔器可能难以看到。
QTableWidget
QTableWidget
是一个在电子表格应用程序中使用的独特小部件。(它也被称为网格小部件)。它是更复杂的小部件之一。在这里,我们只在窗口上显示小部件。
#pragma once #include <QWidget> class Table : public QWidget { public: Table(QWidget *parent = 0); };
该示例的头文件。
#include <QHBoxLayout> #include <QTableWidget> #include "table.h" Table::Table(QWidget *parent) : QWidget(parent) { QHBoxLayout *hbox = new QHBoxLayout(this); QTableWidget *table = new QTableWidget(25, 25, this); hbox->addWidget(table); }
该示例在窗口上显示一个 QTableWidget
。
QTableWidget *table = new QTableWidget(25, 25, this);
在这里,我们创建了一个表格小部件,其中包含 25 行和 25 列。
#include <QApplication> #include "table.h" int main(int argc, char *argv[]) { QApplication app(argc, argv); Table window; window.resize(400, 250); window.setWindowTitle("QTableWidget"); window.show(); return app.exec(); }
这是主文件。

在本章中,我们描述了其他几个 Qt5 小部件。