Qt表格控件
Qt 表格控件 QTableWidget 提供网格形式的数据显示与编辑功能,支持单元格操作、排序、选择、信号槽响应等,适合结构化数据管理。
Qt 表格控件
QTableWidget
QTableWidget
是 Qt 框架中一个非常常用的控件,属于 Qt Widgets 模块,用于在 GUI 中以表格形式显示和编辑数据。它是 QTableView
的一个子类,预置了一个使用 QTableWidgetItem
的模型,适合快速开发带表格的界面。
常用构造函数
1
QTableWidget(int rows, int columns, QWidget *parent = nullptr);
也可以后续动态设置行列数:
1
2
tableWidget->setRowCount(10);
tableWidget->setColumnCount(5);
常用操作示例
设置表头
1
2
QStringList headers = {"Name", "Age", "Score"};
tableWidget->setHorizontalHeaderLabels(headers);
插入单元格内容
1
2
QTableWidgetItem *item = new QTableWidgetItem("Alice");
tableWidget->setItem(0, 0, item);
- 在使用
setItem()
设置表格数据时,如果启用了自动排序功能(setSortingEnabled(true)
),就可能导致还没设置完一整行时,行的位置就被自动移动了,导致显示错乱或逻辑错误。
设置只读单元格
1
item->setFlags(item->flags() & ~Qt::ItemIsEditable);
设置整行选择模式
1
tableWidget->setSelectionBehavior(QAbstractItemView::SelectRows);
响应单元格点击信号
1
2
3
4
connect(tableWidget, &QTableWidget::cellClicked,
[](int row, int column) {
qDebug() << "Clicked cell: " << row << column;
});
进阶功能
排序:
1
tableWidget->setSortingEnabled(true);
自定义单元格(控件嵌入):
1
2
QPushButton *btn = new QPushButton("Click Me");
tableWidget->setCellWidget(0, 1, btn);
清空表格:
1
2
tableWidget->clearContents(); // 保留表头
tableWidget->clear(); // 表头也清除
获取选中项:
1
QList<QTableWidgetItem*> selectedItems = tableWidget->selectedItems();
QTableWidgetItem
QTableWidgetItem
是 Qt 中专门用于 QTableWidget
表格的单元格条目类,它表示表格中的一个单元格对象,可以用于显示文本、图标,也可以设置其行为(如是否可编辑、是否可选中等)。
1
#include <QTableWidgetItem>
它不是控件,而是数据项。每个 QTableWidgetItem
可以包含以下内容:
- 显示内容(文本)
- 图标
- 对齐方式
- 用户自定义数据
- 状态(是否可选中、是否可编辑、是否可拖动)
常用构造函数
1
2
3
QTableWidgetItem();
QTableWidgetItem(const QString &text);
QTableWidgetItem(const QIcon &icon, const QString &text);
典型用法
1
2
QTableWidgetItem *item = new QTableWidgetItem("Hello");
tableWidget->setItem(0, 0, item);
常用设置项
设置对齐方式
1
item->setTextAlignment(Qt::AlignCenter); // 居中对齐
可选项包括:
Qt::AlignLeft
,Qt::AlignRight
,Qt::AlignHCenter
Qt::AlignTop
,Qt::AlignBottom
,Qt::AlignVCenter
设置图标
1
item->setIcon(QIcon(":/icons/user.png"));
也可以直接在构造函数中设置:
1
QTableWidgetItem *item = new QTableWidgetItem(QIcon(":/icons/user.png"), "Alice");
设置字体或颜色
1
2
3
item->setFont(QFont("Arial", 12, QFont::Bold));
item->setForeground(QBrush(Qt::red)); // 文字颜色
item->setBackground(QBrush(Qt::yellow)); // 背景颜色
设置是否可编辑
默认单元格是可编辑的。若要禁用编辑:
1
item->setFlags(item->flags() & ~Qt::ItemIsEditable);
也可以设置为只读 + 不可选中:
1
item->setFlags(Qt::NoItemFlags);
设置和获取用户数据
可以将任意 QVariant 数据附加到条目中:
1
2
item->setData(Qt::UserRole, QVariant(12345));
QVariant val = item->data(Qt::UserRole);
可以用于储存额外信息而不显示在界面上,比如 ID、状态码等。
获取现有单元格项
1
2
3
4
QTableWidgetItem *item = tableWidget->item(row, column);
if (item) {
QString text = item->text();
}
注意事项
QTableWidget
会接管 item 的生命周期,不需要手动删除。设置完
QTableWidgetItem
后,只有使用setItem()
传入到QTableWidget
才会生效。每个
QTableWidgetItem
实例只能存在于一个单元格中,不能复用同一个 item 设置多个格子。
示例代码片段
1
2
3
4
5
6
7
8
9
10
11
12
13
QTableWidget *table = new QTableWidget(3, 2);
table->setHorizontalHeaderLabels({"Name", "Score"});
QTableWidgetItem *item1 = new QTableWidgetItem("Alice");
item1->setTextAlignment(Qt::AlignCenter);
item1->setFont(QFont("Consolas", 12, QFont::Bold));
item1->setForeground(Qt::blue);
QTableWidgetItem *item2 = new QTableWidgetItem("98");
item2->setFlags(item2->flags() & ~Qt::ItemIsEditable); // 设置为只读
table->setItem(0, 0, item1);
table->setItem(0, 1, item2);
表头设置
在 Qt 的 QTableWidget
中,表头(Header) 用于显示每列或每行的标题。可以自定义表头内容、样式、行为等。QTableWidget
默认带有:
- 水平表头(Horizontal Header):表示每一列的标题(如 “姓名”、”年龄”)
- 垂直表头(Vertical Header):表示每一行的编号(如 1、2、3)
设置表头标签
设置列标题(水平表头)
1
2
3
QStringList headers = {"姓名", "年龄", "成绩"};
tableWidget->setColumnCount(headers.size());
tableWidget->setHorizontalHeaderLabels(headers);
设置行标题(垂直表头)
1
2
3
QStringList rowHeaders = {"A", "B", "C"};
tableWidget->setRowCount(rowHeaders.size());
tableWidget->setVerticalHeaderLabels(rowHeaders);
获取表头对象
可以获取表头控件本身,用于进一步设置样式、交互行为:
1
2
QHeaderView *hHeader = tableWidget->horizontalHeader(); // 横向表头
QHeaderView *vHeader = tableWidget->verticalHeader(); // 纵向表头
常用表头配置操作
设置列宽 / 行高自适应内容
1
2
tableWidget->resizeColumnsToContents(); // 自动调整列宽
tableWidget->resizeRowsToContents(); // 自动调整行高
禁用用户点击表头排序
1
tableWidget->setSortingEnabled(false);
或禁止交互:
1
tableWidget->horizontalHeader()->setSectionsClickable(false);
固定列宽 / 不可拖动调整宽度
1
2
tableWidget->horizontalHeader()->setSectionResizeMode(QHeaderView::Fixed);
tableWidget->setColumnWidth(0, 100); // 第0列设为100像素宽
如果要让所有列等宽分布:
1
tableWidget->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch);
隐藏表头
1
2
tableWidget->horizontalHeader()->setVisible(false); // 隐藏列标题
tableWidget->verticalHeader()->setVisible(false); // 隐藏行编号
进阶:自定义表头样式
可以使用 QSS(Qt Style Sheet)自定义表头的外观:
1
2
3
tableWidget->setStyleSheet(
"QHeaderView::section { background-color: lightgray; color: black; font-weight: bold; }"
);
选中区域和选中行为
在 QTableWidget
中,选中区域(Selection Range) 和 选中行为(Selection Behavior) 是非常重要的交互特性,决定了用户如何选中单元格、选中的范围、以及你如何从代码中获取这些选中的内容。
选中行为(Selection Behavior)
通过 setSelectionBehavior()
设置,控制用户点击时,选择的是哪一部分。
可选项如下:
行为常量 | 说明 |
---|---|
QAbstractItemView::SelectItems | 默认,选中单元格 |
QAbstractItemView::SelectRows | 点击任意单元格会选中整行 |
QAbstractItemView::SelectColumns | 点击任意单元格会选中整列 |
示例:
1
tableWidget->setSelectionBehavior(QAbstractItemView::SelectRows);
选中模式(Selection Mode)
通过 setSelectionMode()
设置,控制能不能多选、是否允许框选等。
可选项如下:
模式常量 | 说明 |
---|---|
QAbstractItemView::NoSelection | 禁止选择 |
QAbstractItemView::SingleSelection | 一次只能选一个区域(行/列/单元格) |
QAbstractItemView::MultiSelection | 可使用 Ctrl 多选多个单元格(仅配合 SelectItems ) |
QAbstractItemView::ExtendedSelection | 默认,支持 Shift/Ctrl 多选 |
QAbstractItemView::ContiguousSelection | 只能选连续区域 |
示例:
1
tableWidget->setSelectionMode(QAbstractItemView::ExtendedSelection);
获取选中区域数据
获取所有选中的单元格
1
2
3
4
QList<QTableWidgetItem*> selectedItems = tableWidget->selectedItems();
for (QTableWidgetItem* item : selectedItems) {
qDebug() << item->row() << item->column() << item->text();
}
获取所有选中的行号(常用于 SelectRows
模式)
1
2
3
4
5
QItemSelectionModel *sel = tableWidget->selectionModel();
QModelIndexList selected = sel->selectedRows(); // 获取选中的行
for (const QModelIndex &index : selected) {
qDebug() << "Selected row:" << index.row();
}
获取选中区域(多个矩形)
1
2
3
4
5
6
7
8
QList<QTableWidgetSelectionRange> ranges = tableWidget->selectedRanges();
for (const QTableWidgetSelectionRange &range : ranges) {
int topRow = range.topRow();
int bottomRow = range.bottomRow();
int leftCol = range.leftColumn();
int rightCol = range.rightColumn();
qDebug() << "Selected block from" << topRow << leftCol << "to" << bottomRow << rightCol;
}
设置或取消选中项(代码中)
选中一个单元格
1
tableWidget->setCurrentCell(2, 1); // 选中第3行第2列
清除所有选中状态
1
tableWidget->clearSelection();
示例代码:选中整行并打印内容
1
2
3
4
5
6
7
8
9
tableWidget->setSelectionBehavior(QAbstractItemView::SelectRows);
tableWidget->setSelectionMode(QAbstractItemView::SingleSelection);
connect(tableWidget, &QTableWidget::itemSelectionChanged, [=]() {
QList<QTableWidgetItem*> selected = tableWidget->selectedItems();
for (QTableWidgetItem *item : selected) {
qDebug() << "Row:" << item->row() << "Col:" << item->column() << "Text:" << item->text();
}
});
示例:个人信息表
widget.ui
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>Widget</class>
<widget class="QWidget" name="Widget">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>400</width>
<height>360</height>
</rect>
</property>
<property name="windowTitle">
<string>Widget</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QTableWidget" name="tableWidget">
<property name="rowCount">
<number>2</number>
</property>
<row/>
<row/>
<column>
<property name="text">
<string>姓名</string>
</property>
</column>
<column>
<property name="text">
<string>性别</string>
</property>
</column>
<column>
<property name="text">
<string>生日</string>
</property>
</column>
<column>
<property name="text">
<string>婚否</string>
</property>
</column>
<column>
<property name="text">
<string>住址</string>
</property>
</column>
<item row="0" column="0">
<property name="text">
<string>梁山伯</string>
</property>
<property name="icon">
<iconset resource="photos.qrc">
<normaloff>:/images/butterfly01.png</normaloff>:/images/butterfly01.png</iconset>
</property>
</item>
<item row="0" column="1">
<property name="text">
<string>男</string>
</property>
</item>
<item row="0" column="2">
<property name="text">
<string>300/3/3</string>
</property>
</item>
<item row="0" column="3">
<property name="text">
<string/>
</property>
<property name="checkState">
<enum>Checked</enum>
</property>
</item>
<item row="0" column="4">
<property name="text">
<string>梁家村</string>
</property>
</item>
<item row="1" column="0">
<property name="text">
<string>祝英台</string>
</property>
<property name="icon">
<iconset resource="photos.qrc">
<normaloff>:/images/butterfly02.png</normaloff>:/images/butterfly02.png</iconset>
</property>
</item>
<item row="1" column="1">
<property name="text">
<string>女</string>
</property>
</item>
<item row="1" column="2">
<property name="text">
<string>301/4/4</string>
</property>
</item>
<item row="1" column="3">
<property name="checkState">
<enum>Checked</enum>
</property>
</item>
<item row="1" column="4">
<property name="text">
<string>祝家庄</string>
</property>
</item>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_2">
<item>
<widget class="QLabel" name="label">
<property name="text">
<string>姓名</string>
</property>
</widget>
</item>
<item>
<widget class="QLineEdit" name="lineEditName"/>
</item>
<item>
<widget class="QLabel" name="label_4">
<property name="text">
<string>头像</string>
</property>
</widget>
</item>
<item>
<widget class="QComboBox" name="comboBoxPhotos">
<item>
<property name="text">
<string> </string>
</property>
<property name="icon">
<iconset resource="photos.qrc">
<normaloff>:/images/butterfly01.png</normaloff>:/images/butterfly01.png</iconset>
</property>
</item>
<item>
<property name="text">
<string> </string>
</property>
<property name="icon">
<iconset resource="photos.qrc">
<normaloff>:/images/butterfly02.png</normaloff>:/images/butterfly02.png</iconset>
</property>
</item>
<item>
<property name="text">
<string> </string>
</property>
<property name="icon">
<iconset resource="photos.qrc">
<normaloff>:/images/cute01.png</normaloff>:/images/cute01.png</iconset>
</property>
</item>
<item>
<property name="text">
<string> </string>
</property>
<property name="icon">
<iconset resource="photos.qrc">
<normaloff>:/images/cute02.png</normaloff>:/images/cute02.png</iconset>
</property>
</item>
<item>
<property name="text">
<string> </string>
</property>
<property name="icon">
<iconset resource="photos.qrc">
<normaloff>:/images/toofat.png</normaloff>:/images/toofat.png</iconset>
</property>
</item>
</widget>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_3">
<item>
<widget class="QLabel" name="label_2">
<property name="text">
<string>性别</string>
</property>
</widget>
</item>
<item>
<widget class="QLineEdit" name="lineEditGender"/>
</item>
<item>
<widget class="QLabel" name="label_5">
<property name="text">
<string>生日</string>
</property>
</widget>
</item>
<item>
<widget class="QDateEdit" name="dateEdit"/>
</item>
<item>
<widget class="QCheckBox" name="checkBoxIsMarried">
<property name="text">
<string>婚否</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_4">
<item>
<widget class="QLabel" name="label_3">
<property name="text">
<string>住址</string>
</property>
</widget>
</item>
<item>
<widget class="QLineEdit" name="lineEditAddress"/>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Orientation::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QPushButton" name="btnAdd">
<property name="text">
<string>添加</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="btnDel">
<property name="text">
<string>删除</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_2">
<property name="orientation">
<enum>Qt::Orientation::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
</layout>
</widget>
<resources>
<include location="photos.qrc"/>
</resources>
<connections/>
</ui>
widget.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
#ifndef WIDGET_H
#define WIDGET_H
#include <QTableWidgetItem>
#include <QWidget>
QT_BEGIN_NAMESPACE
namespace Ui {
class Widget;
}
QT_END_NAMESPACE
class Widget : public QWidget {
Q_OBJECT
public:
Widget(QWidget* parent = nullptr);
~Widget();
private slots:
void on_tableWidget_currentItemChanged(QTableWidgetItem* current, QTableWidgetItem* previous);
void on_btnAdd_clicked();
void on_btnDel_clicked();
private:
Ui::Widget* ui;
};
#endif // WIDGET_H
widget.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
#include "widget.h"
#include "./ui_widget.h"
#include <QMessageBox>
// 构造函数,初始化界面和控件设置
Widget::Widget(QWidget* parent) : QWidget(parent), ui(new Ui::Widget) {
ui->setupUi(this); // 加载 UI 设计器生成的界面
// 设置日期编辑器可以弹出日历控件,方便用户选择日期
ui->dateEdit->setCalendarPopup(true);
// 设置表格控件的行为
// 每次选中整行
ui->tableWidget->setSelectionBehavior(QAbstractItemView::SelectRows);
// 设置只能单选,方便后续删除功能的使用
ui->tableWidget->setSelectionMode(QAbstractItemView::SingleSelection);
// 启用自动排序(会根据列头点击进行排序)
ui->tableWidget->setSortingEnabled(true);
// 默认按第 0 列升序排序
ui->tableWidget->sortByColumn(0, Qt::AscendingOrder);
// 让表格的最后一列自动拉伸填满剩余空间
ui->tableWidget->horizontalHeader()->setStretchLastSection(true);
// 设置行高,让图标更大一些看起来更美观
ui->tableWidget->verticalHeader()->setDefaultSectionSize(36);
// 设置图标大小
ui->tableWidget->setIconSize(QSize(32, 32));
// 修改主窗口宽度,便于展示表格拉伸效果
QSize sz = this->size();
sz.setWidth(640);
this->resize(sz);
}
// 析构函数,释放 UI 内存
Widget::~Widget() {
delete ui;
}
// 当前选中项发生变化时触发
void Widget::on_tableWidget_currentItemChanged(QTableWidgetItem* current, QTableWidgetItem* previous) {
// 打印当前条目的行、列、文本内容
if (current != nullptr) qDebug() << tr("当前条目行号:%1,列号:%2,文本:%3").arg(current->row()).arg(current->column()).arg(current->text());
}
// 添加按钮点击事件
void Widget::on_btnAdd_clicked() {
QString strName = ui->lineEditName->text().trimmed(); // 获取姓名并去掉前后空格
if (strName.isEmpty()) {
QMessageBox::warning(this, tr("添加行"), tr("姓名不能为空!"));
return;
}
// 添加数据时必须先关闭排序,否则新行可能会被移动,导致 setItem 设置错误
ui->tableWidget->setSortingEnabled(false);
// 获取当前行数,准备插入新行
int nOldRowCount = ui->tableWidget->rowCount();
ui->tableWidget->insertRow(nOldRowCount); // 在末尾插入一行
// 头像图标(从下拉框当前项获取)
QIcon iconHead = ui->comboBoxPhotos->itemIcon(ui->comboBoxPhotos->currentIndex());
// 创建带图标和文本的姓名项
QTableWidgetItem* itemName = new QTableWidgetItem(iconHead, strName);
ui->tableWidget->setItem(nOldRowCount, 0, itemName);
// 性别
QString strGender = ui->lineEditGender->text();
QTableWidgetItem* itemGender = new QTableWidgetItem(strGender);
ui->tableWidget->setItem(nOldRowCount, 1, itemGender);
// 生日(格式化为 yyyy/MM/dd)
QString strBirthday = ui->dateEdit->date().toString("yyyy/MM/dd");
QTableWidgetItem* itemBirthday = new QTableWidgetItem(strBirthday);
ui->tableWidget->setItem(nOldRowCount, 2, itemBirthday);
// 婚否(复选框形式)
Qt::CheckState cks = ui->checkBoxIsMarried->checkState();
QTableWidgetItem* itemIsMarried = new QTableWidgetItem();
itemIsMarried->setCheckState(cks); // 设置复选框状态
ui->tableWidget->setItem(nOldRowCount, 3, itemIsMarried);
// 地址
QString strAddress = ui->lineEditAddress->text();
QTableWidgetItem* itemAddress = new QTableWidgetItem(strAddress);
ui->tableWidget->setItem(nOldRowCount, 4, itemAddress);
// 添加完毕后重新开启排序
ui->tableWidget->setSortingEnabled(true);
ui->tableWidget->sortByColumn(0, Qt::AscendingOrder);
// 设置当前选中的单元格为刚插入的 itemName 并滚动到它
ui->tableWidget->setCurrentItem(itemName);
ui->tableWidget->scrollToItem(itemName);
}
// 删除按钮点击事件
void Widget::on_btnDel_clicked() {
// 获取当前选中的单元格
QTableWidgetItem* curItem = ui->tableWidget->currentItem();
if (curItem == nullptr) return; // 没有选中时直接返回
// 如果当前单元格被选中,删除其所在行
if (curItem->isSelected()) ui->tableWidget->removeRow(curItem->row());
}
示例:成绩表
widget.ui
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>Widget</class>
<widget class="QWidget" name="Widget">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>480</width>
<height>400</height>
</rect>
</property>
<property name="windowTitle">
<string>Widget</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QTableWidget" name="tableWidget"/>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QLabel" name="label">
<property name="text">
<string>指定列</string>
</property>
</widget>
</item>
<item>
<widget class="QComboBox" name="comboBoxColumns">
<item>
<property name="text">
<string>语文</string>
</property>
</item>
<item>
<property name="text">
<string>数学</string>
</property>
</item>
<item>
<property name="text">
<string>英语</string>
</property>
</item>
<item>
<property name="text">
<string>物理</string>
</property>
</item>
</widget>
</item>
<item>
<widget class="QLabel" name="label_2">
<property name="text">
<string>分值</string>
</property>
</widget>
</item>
<item>
<widget class="QComboBox" name="comboBoxCompares">
<item>
<property name="text">
<string>==</string>
</property>
</item>
<item>
<property name="text">
<string><=</string>
</property>
</item>
<item>
<property name="text">
<string>>=</string>
</property>
</item>
</widget>
</item>
<item>
<widget class="QLineEdit" name="lineEditFindText"/>
</item>
<item>
<widget class="QPushButton" name="btnFind">
<property name="text">
<string>查找</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_2">
<item>
<widget class="QLabel" name="label_3">
<property name="text">
<string>姓名</string>
</property>
</widget>
</item>
<item>
<widget class="QLineEdit" name="lineEditName"/>
</item>
<item>
<widget class="QPushButton" name="btnAddLines">
<property name="text">
<string>增加行</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="btnDelLines">
<property name="text">
<string>删除选中行</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="btnDesSelectedItems">
<property name="text">
<string>删除选中条目</string>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>
widget.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
#ifndef WIDGET_H
#define WIDGET_H
#include <QWidget>
QT_BEGIN_NAMESPACE
namespace Ui {
class Widget;
}
QT_END_NAMESPACE
class Widget : public QWidget {
Q_OBJECT
public:
Widget(QWidget* parent = nullptr);
~Widget();
private slots:
void on_tableWidget_itemSelectionChanged();
void on_btnFind_clicked();
void on_btnAddLines_clicked();
void on_btnDelLines_clicked();
void on_btnDesSelectedItems_clicked();
private:
Ui::Widget* ui;
// 初始化表格函数
void InitScoresTable();
// 设置某行的行首和四个单元格
void SetTableRow(int nRow, QString strName, QString strChinese, QString strMath, QString strForeignLanguage, QString strFood);
};
#endif // WIDGET_H
widget.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
#include "widget.h"
#include "./ui_widget.h"
#include <QDebug>
#include <QMessageBox>
#include <QTableWidgetItem> // 表格条目
#include <QTableWidgetSelectionRange> // 表格选中区域
Widget::Widget(QWidget* parent) : QWidget(parent), ui(new Ui::Widget) {
ui->setupUi(this);
InitScoresTable(); // 初始化表格
}
Widget::~Widget() {
delete ui;
}
// 初始化成绩表格
void Widget::InitScoresTable() {
ui->tableWidget->setRowCount(2); // 设置2行
ui->tableWidget->setColumnCount(4); // 设罤列
// 列标题
QStringList listHeaders;
listHeaders << tr("语文") << tr(" 数学") << tr(" 外语") << tr(" 物理");
ui->tableWidget->setHorizontalHeaderLabels(listHeaders);
// 初始化两行数据
SetTableRow(0, tr(" 小明"), tr("66"), tr("77"), tr("88"), tr("99"));
SetTableRow(1, tr(" 小萌"), tr("99"), tr("88"), tr("77"), tr("66"));
}
// 设置指定行数据
void Widget::SetTableRow(int nRow, QString strName, QString strChinese, QString strMath, QString strForeignLanguage, QString strPhysic) {
// 行头姓名
QTableWidgetItem* itemName = new QTableWidgetItem(strName);
ui->tableWidget->setVerticalHeaderItem(nRow, itemName);
// 各科成绩
ui->tableWidget->setItem(nRow, 0, new QTableWidgetItem(strChinese));
ui->tableWidget->setItem(nRow, 1, new QTableWidgetItem(strMath));
ui->tableWidget->setItem(nRow, 2, new QTableWidgetItem(strForeignLanguage));
ui->tableWidget->setItem(nRow, 3, new QTableWidgetItem(strPhysic));
}
// 选择改变时执行
void Widget::on_tableWidget_itemSelectionChanged() {
QList<QTableWidgetItem*> listItems = ui->tableWidget->selectedItems();
QList<QTableWidgetSelectionRange> listRanges = ui->tableWidget->selectedRanges();
int nItemsCount = listItems.count();
int nRangesCount = listRanges.count();
int nCellsCount = 0;
// 统计选中单元格数量
for(int i = 0; i < nRangesCount; i++) {
nCellsCount += listRanges[i].rowCount() * listRanges[i].columnCount();
}
// 输出选择信息
qDebug() << tr(" 选中条目数:%1,选中区域数:%2,选中单元格数:%3")
.arg(nItemsCount).arg(nRangesCount).arg(nCellsCount);
}
// 搜索匹配条目
void Widget::on_btnFind_clicked() {
QString strDstScore = ui->lineEditFindText->text().trimmed();
if(strDstScore.isEmpty()) return;
int nDstScore = strDstScore.toInt();
int nTheColumn = ui->comboBoxColumns->currentIndex();
int nCompare = ui->comboBoxCompares->currentIndex();
int nRowCount = ui->tableWidget->rowCount();
int nFilteredCount = 0;
double dblTotal = 0;
double dblAverage = 0;
QTableWidgetItem *itemFilteredFirst = nullptr;
ui->tableWidget->setCurrentItem(nullptr, QItemSelectionModel::Clear); // 清除选中
// 遍历表格查找符合条件的条目
for(int i = 0; i < nRowCount; i++) {
QTableWidgetItem *itemCur = ui->tableWidget->item(i, nTheColumn);
if(!itemCur) continue;
int nCurScore = itemCur->text().trimmed().toInt();
bool match = false;
if(nCompare == 0 && nCurScore == nDstScore)
match = true;
else if(nCompare == 1 && nCurScore <= nDstScore)
match = true;
else if(nCompare == 2 && nCurScore >= nDstScore)
match = true;
if(match) {
nFilteredCount++;
dblTotal += nCurScore;
itemCur->setSelected(true);
if(!itemFilteredFirst) {
itemFilteredFirst = itemCur;
ui->tableWidget->setCurrentItem(itemCur);
ui->tableWidget->scrollToItem(itemCur);
}
}
}
if(nFilteredCount > 0)
dblAverage = dblTotal / nFilteredCount;
QString strMsg = tr(" 匹配条目数:%1,总值:%2,均值:%3")
.arg(nFilteredCount).arg(dblTotal).arg(dblAverage);
QMessageBox::information(this, tr(" 查找"), strMsg);
ui->tableWidget->setFocus(); // 让高亮选择显示
}
// 添加新行
void Widget::on_btnAddLines_clicked() {
QString strName = ui->lineEditName->text().trimmed();
if(strName.isEmpty()) return;
int nOldRowCount = ui->tableWidget->rowCount();
ui->tableWidget->insertRow(nOldRowCount);
SetTableRow(nOldRowCount, strName, tr("0"), tr("0"), tr("0"), tr("0"));
ui->tableWidget->scrollToBottom();
}
// 删除选中行
void Widget::on_btnDelLines_clicked() {
QList<int> listRowIndex;
QList<QTableWidgetSelectionRange> listRanges = ui->tableWidget->selectedRanges();
if(listRanges.isEmpty()) return;
// 编集所有选中行号
for(const auto &range : listRanges) {
for(int j = 0; j < range.rowCount(); j++) {
int nRowIndex = range.topRow() + j;
if(!listRowIndex.contains(nRowIndex))
listRowIndex.append(nRowIndex);
}
}
std::sort(listRowIndex.begin(), listRowIndex.end()); // 排序后选择末尾删除
for(int i = listRowIndex.count() - 1; i >= 0; i--) {
ui->tableWidget->removeRow(listRowIndex[i]);
}
}
// 删除选中单元格
void Widget::on_btnDesSelectedItems_clicked() {
QList<QTableWidgetItem*> listItems = ui->tableWidget->selectedItems();
if(listItems.isEmpty()) return;
for(auto item : listItems) {
int row = item->row();
int col = item->column();
delete ui->tableWidget->takeItem(row, col); // 删除单元格
}
}