在Qt5 C++编程教程的这一部分,我们将继续谈论Qt5的部件。我们涵盖了以下部件: QCheckBox, QListWidget, QProgressBar, QPixmap, QSplitter, 和QTableWidget。
QCheckBox
QCheckBox是一个具有两种状态(开/关)的小部件。它是一个带有标签的框,如果勾选了复选框,则框内会显示一个勾号。
在我们的示例中,我们在窗口上显示一个复选框。如果选中复选框,则显示窗口的标题,否则将隐藏标题。
checkbox.h
#pragma once
#include <QWidget>
class CheckBox : public QWidget {
Q_OBJECT
public:
CheckBox(QWidget *parent = 0);
private slots:
void showTitle(int);
};
checkbox.cpp
#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。
main.cpp
#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是一个用于显示项目列表的部件。在我们的例子中,我们将演示如何在列表部件中添加、重命名和删除项目。
listwidget.h
#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;
};
The header file for the example.
listwidget.cpp
#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方法向列表部件添加一个新项目。该方法会弹出一个输入对话框。对话框返回一个字符串值。我们使用简化方法从字符串中去除可能的空白。如果返回的字符串不是空的,我们就把它添加到列表部件中,在列表的最后。最后,我们用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对话框中。从对话框中返回的字符串被简化方法处理,以去除潜在的空白。然后我们用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();
}
}
清除方法将所有项目从列表部件中移除。
main.cpp
#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用于向用户指示操作的进度。
progressbar.h
#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();
};
progressbar.cpp
#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和两个push button。其中一个按钮启动计时器,进而更新进度条。另一个按钮停止计时器。
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更新进度条的当前值。
main.cpp
#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在窗口上显示一张图片。
pixmap.h
#pragma once
#include <QWidget>
class Pixmap : public QWidget {
public:
Pixmap(QWidget *parent = 0);
};
pixmap.cpp
#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);
我们创建一个pixmap并将其放入标签小部件中。
main.cpp
#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是一个Qt小部件,允许用户通过拖拽子部件之间的边界来控制它们的大小。在这个例子中,我们展示了三个QFrame小部件,它们被两个分隔符控制。
splitter.h
#pragma once
#include <QWidget>
class Splitter : public QWidget {
public:
Splitter(QWidget *parent = 0);
};
splitter.cpp
#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方法,我们为分隔符的子小部件设置了大小。
main.cpp
#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是一种在电子表格应用程序中使用的特殊部件(也称为网格部件)。它是比较复杂的部件之一。以下代码仅显示在窗口上。
table.h
#pragma once
#include <QWidget>
class Table : public QWidget {
public:
Table(QWidget *parent = 0);
};The header file for the example.
table.cpp
#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列的表部件。
main.cpp
#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();
}