Qt5作为一个功能强大且跨平台的GUI框架,其丰富的控件库就像一个"控件超级城"。从简单的按钮到复杂的树形视图,从单行文本到带格式的富文本编辑,Qt5应有尽有。今天我们就来领略Qt5控件的魅力,掌握各种常用控件的使用技巧,助你在GUI开发之路畅行无阻!



一、基础控件: 打好根基



1、QPushButton: 经典按钮

QPushButton *btn = new QPushButton("Click Me");
connect(btn, &QPushButton::clicked, []{ qDebug() << "Button clicked"; });

QPushButton是最基本的按钮控件,可以监听其clicked信号并连接相应的槽函数。除此之外,还可以设置按钮的图标、快捷键、自动重复等属性。



2、QLabel: 随处可见的标签

QLabel *label = new QLabel("Hello Qt!");
label->setAlignment(Qt::AlignCenter); // 设置居中对齐

QLabel可以显示文本或图片,非常适合做提示、标题等用途。通过富文本的支持,还能方便地设置格式化的富文本内容。



3、QLineEdit & QTextEdit: 新高度的文本编辑

QLineEdit *lineEdit = new QLineEdit;
lineEdit->setPlaceholderText("Enter some text...");
lineEdit->setText("Hello Qt!");

QTextEdit *textEdit = new QTextEdit;
textEdit->setPlainText("Hello Qt!\nThis is some sample text.");
textEdit->setFontFamily("Courier");

QLineEdit是单行文本编辑框,QTextEdit则支持多行、富文本编辑,功能更加强大。二者都提供了查找/替换、撤销/重做等常用操作。



4、选择控件: 显示和获取用户输入

QComboBox & QFontComboBox: 下拉选择

QComboBox *combo = new QComboBox;
combo->addItem("Option 1");
combo->addItem("Option 2");
combo->addItems({"Option 3", "Option 4"});

QFontComboBox *fontCombo = new QFontComboBox;
fontCombo->setCurrentFont(QFont("Times", 12));

QComboBox用于在多个选项中选择一项,支持可编辑模式;QFontComboBox则专门用于选择字体,免去了手动添加字体的麻烦。



5、QSpinBox & 日期/时间编辑控件

QSpinBox *spinBox = new QSpinBox;
spinBox->setRange(0, 100); // 设置值域范围
spinBox->setValue(42); // 设置当前值

QDateEdit *dateEdit = new QDateEdit(QDate::currentDate());
dateEdit->setCalendarPopup(true); // 显示日历选择框

QTimeEdit *timeEdit = new QTimeEdit(QTime::currentTime());
timeEdit->setDisplayFormat("hh:mm:ss"); // 设置时间显示格式

QSpinBox可以通过点击箭头或手动输入的方式编辑数值;QDateEdit和QTimeEdit则分别提供了日期和时间的编辑能力,显示格式可自定义。



6、QScrollBar: 在有限空间滚动内容

QScrollBar *hBar = new QScrollBar(Qt::Horizontal);
hBar->setRange(0, 100); // 设置值域范围
hBar->setValue(25); // 设置当前滚动位置

QScrollBar *vBar = new QScrollBar(Qt::Vertical);
vBar->setRange(0, 1000);
vBar->setValue(500);

QScrollBar横向或纵向滚动条控件,通常用于在有限的视图空间中滚动显示内容。可以方便地设置其值域范围和当前值等。



7、QRadioButton & QCheckBox: 是或否你说了算

QRadioButton *radioBtn1 = new QRadioButton("Option 1");
QRadioButton *radioBtn2 = new QRadioButton("Option 2");
radioBtn1->setChecked(true);

QCheckBox *checkBox = new QCheckBox("Check Me");
checkBox->setTristate(true); // 设置为三态模式
checkBox->setCheckState(Qt::PartiallyChecked); // 设置为半选中态

QRadioButton是单选按钮,同一组内只能选中一个;QCheckBox是多选框,支持简单的勾选或者三态(完全选中、未选中、半选中)等模式。



二、数据视图: 用最通用的方式显示任何数据



Qt5中提供了一整套强大的模型-视图框架,用于通用地显示列表、树形和表格形式的数据。数据视图支持自定义代理、编辑和拖放等高级特性。


1、QListView: 线性列表视图

QStringListModel *model = new QStringListModel;
QStringList data;
data << "Item 1" << "Item 2" << "Item 3";
model->setStringList(data);

QListView *listView = new QListView;
listView->setModel(model);
listView->setEditTriggers(QAbstractItemView::DoubleClicked); // 双击编辑

QListView将一维线性数据以列表视图的形式显示,可以使用任何数据模型作为数据源。



### 2、QTreeView: 层级树形视图

QStandardItemModel *model = new QStandardItemModel;
QStandardItem *rootNode = model->invisibleRootItem();

QStandardItem *node1 = new QStandardItem("Node 1");
QStandardItem *node2 = new QStandardItem("Node 2");
rootNode->appendRow(node1);
rootNode->appendRow(node2);

QTreeView *treeView = new QTreeView;
treeView->setModel(model);
treeView->expandAll(); // 展开所有节点

QTreeView以树形结构的形式显示层级数据,支持节点的展开、折叠等操作。可以使用QStandardItemModel或者自定义模型作为其数据源。



3、QTableView: 网格表格视图

QStandardItemModel *model = new QStandardItemModel(4, 4); // 4行4列
model->setHorizontalHeaderLabels({"Column 1", "Column 2", "Column 3", "Column 4"});
  
for (int row = 0; row < 4; ++row) {
    for (int column = 0; column < 4; ++column) {
        QModelIndex index = model->index(row, column);
        model->setData(index, QString("Row %1, Column %2").arg(row + 1).arg(column + 1));
    }
}

QTableView *tableView = new QTableView;
tableView->setModel(model);
tableView->resizeColumnsToContents(); // 根据内容调整列宽

QTableView以二维表格的形式显示行列数据,能够展示最复杂的网格状数据集。可可以使用QStandardItemModel或者自定义模型作为其数据源。



三、高级数据视图玩法



上面我们介绍了QListView、QTreeView和QTableView这三种最常用的通用数据视图,它们已经相当强大和灵活。但Qt5在这方面的能力远不止于此,还提供了很多定制化选项和高级特性,让我们一一领略。


1、自定义代理:掌控数据在视图中的显示方式

Qt的模型-视图架构允许我们通过实现自定义代理(QAbstractItemDelegate)来自定义数据在视图中的显示和编辑行为。比如:

// MyDelegate.h
#include <QStyledItemDelegate>

class MyDelegate : public QStyledItemDelegate
{
    Q_OBJECT
public:
    explicit MyDelegate(QObject *parent = nullptr);

    void paint(QPainter *painter, const QStyleOptionViewItem &option,
               const QModelIndex &index) const override;
    QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &option,
                          const QModelIndex &index) const override;
};

在paint()函数中,我们可以自定义每个单元格的渲染方式,实现诸如条形进度显示、颜色代码等自定义需求。

而createEditor()则让我们能为指定的数据类型提供自定义的编辑控件,比如为颜色数据使用一个QColorDialog。



2、自定义视图:打造属于你自己的视图

有时候Qt内置的视图还不够用?没关系,Qt5允许我们通过继承QAbstractItemView来自定义视图的各个方面,如选择行为、编辑模式、拖拽支持等等。

比如我们可以实现一个日历视图:

class CalendarView : public QAbstractItemView
{
    Q_OBJECT
public:
    explicit CalendarView(QWidget *parent = nullptr);

    QRect visualRect(const QModelIndex &index) const override;
    void scrollTo(const QModelIndex &index, ScrollHint hint = EnsureVisible) override;
    QModelIndex indexAt(const QPoint &point) const override;

protected:
    QModelIndex moveCursor(QAbstractItemView::CursorAction cursorAction,
                           Qt::KeyboardModifiers modifiers) override;

    int horizontalOffset() const override;
    int verticalOffset() const override;

    bool isIndexHidden(const QModelIndex &index) const override;

    void setSelection(const QRect &rect, QItemSelectionModel::SelectionFlags command) override;

    void paintEvent(QPaintEvent *event) override;

    QRegion visualRegionForSelection(const QItemSelection &selection) const override;

private:
    // ... 其他成员函数和数据
};

通过reimplementation这些纯虚函数,我们就能完全控制视图的外观、布局、滚动、选择等各个行为,实现最符合需求的自定义视图。



3、模型视图的高级玩法

最后,Qt还为模型-视图框架提供了很多其他高级特性:

  • 模型合并(QConcatenateTablesProxyModel): 将多个模型合并为一个统一视图
  • 模型视图关联(QModelIndexWidget): 将视图embedded到模型索引项中
  • 模型视图映射(QModelIndexMapper): 实现模型索引到窗口部件属性的自动映射
  • 视图同步(QAbstractItemViewFromBuilder): 同步多个视图在选择、滚动等行为上的一致性

这些高级工具让我们能以更优雅和模块化的方式开发复杂的数据驱动应用。受益于Qt强大的模型-视图架构,我们能以更低的开发成本打造出高质量且行为一致的用户界面。



四、结语

通过今天的分享,相信你已经对Qt5的控件系统有了更加全面的认识。无论是从基础的按钮、标签、文本框到高级的列表、树形和表格视图,Qt5控件无所不能。同时,Qt5强大的自定义机制和扩展性也让我们能为任何特定场景打造量身定制的解决方案。



控件固然重要,但仅仅掌握控件知识还远远不够。一个出色的应用程序不应是简单堆砌控件的产物,更应该具备现代化、动态、跨平台等特性。值得庆幸的是,Qt5已经为我们在这些方面做好了充分准备。虽然Qt5已经为我们提供了强大的武器库,但需要我们自己去勇敢尝试和创新。



那么,你最喜欢哪些Qt5控件呢?你期待Qt在未来为我们带来怎样的惊喜呢?让我们拭目以待,共同分享学习的乐趣!