QTableWidget 是 Qt 提供的一个基于项的表格控件,继承自 QTableView。它允许开发者以行列形式展示和编辑数据,支持表头、单元格合并、样式定制等功能。与 QTableView 相比,QTableWidget 更加简单易用,适合快速开发小型表格应用。
1.创建表格
首先,我们需要创建一个 QTableWidget 并设置其行列数:
QTableWidget* tableWidget = new QTableWidget(5, 3); // 5行3列
2.设置表头
表头分为水平表头和垂直表头。我们可以通过以下代码设置表头标签:
QStringList headers;
headers << "姓名" << "年龄" << "城市";
tableWidget->setHorizontalHeaderLabels(headers);
3.设置和获取单元格内的小部件
void QTableWidget::setCellWidget 用于将一个小部件(widget)设置到表格的指定单元格中。通过这个函数,可以在表格的某个单元格中嵌入自定义的小部件,例如按钮、下拉框、进度条等,从而实现更复杂的交互和显示功能。
函数原型:
void QTableWidget::setCellWidget(int row, int column, QWidget* widget);
设置单元格小部件:
// 创建一个 4x4 的表格
QTableWidget tableWidget(4, 4);
tableWidget.setWindowTitle("QTableWidget Example");
// 在 (0, 0) 单元格中设置一个 QPushButton
QPushButton* button = new QPushButton("Click Me", &tableWidget);
tableWidget.setCellWidget(0, 0, button);
// 在 (1, 1) 单元格中设置一个 QComboBox
QComboBox* comboBox = new QComboBox(&tableWidget);
comboBox->addItems({"Option 1", "Option 2", "Option 3"});
tableWidget.setCellWidget(1, 1, comboBox);
// 在 (2, 2) 单元格中设置一个 QProgressBar
QProgressBar* progressBar = new QProgressBar(&tableWidget);
progressBar->setValue(50);
tableWidget.setCellWidget(2, 2, progressBar);
// 在 (3, 3) 单元格中设置一个 QLabel(显示图片)
QLabel* label = new QLabel(&tableWidget);
label->setPixmap(QPixmap(":/images/icon.png"));
tableWidget.setCellWidget(3, 3, label);
获取单元格小部件:
// 获取 (0, 0) 单元格中的小部件
QWidget* widget = tableWidget->cellWidget(0, 0);
if (widget) {
qDebug() << "Widget found in cell (0, 0)";
if (QPushButton* button = qobject_cast<QPushButton*>(widget)) {
qDebug() << "The widget is a QPushButton with text:" << button->text();
}
} else {
qDebug() << "No widget in cell (0, 0)";
}
注意事项:
- 设置到单元格中的小部件由 QTableWidget 自动管理其生命周期。当表格被销毁时,这些小部件也会被自动销毁。
- 设置小部件会覆盖单元格的默认内容(如文本或图标)。如果需要同时显示文本和小部件,可以将小部件和文本结合使用(例如在 QLabel 中显示文本)。
4.打开和关闭持久编辑器
void QTableWidget::openPersistentEditor(QTableWidgetItem *item) 用于为指定的 QTableWidgetItem 打开一个持久编辑器(persistent editor)。持久编辑器会一直显示在单元格中,直到显式调用 closePersistentEditor 关闭它。
作用:
- 打开持久编辑器:为指定的 QTableWidgetItem 打开一个编辑器(例如 QLineEdit、QComboBox 等),并使其一直保持显示状态。
- 允许持续编辑:与普通的编辑器(通过双击单元格或调用 editItem 打开)不同,持久编辑器不会在失去焦点时自动关闭,而是会一直显示,直到显式关闭。
函数原型:
void QTableWidget::openPersistentEditor(QTableWidgetItem *item);
参数:QTableWidgetItem *item:需要打开持久编辑器的单元格项。如果 item 为 nullptr,则函数不会执行任何操作。
典型用途:
- 嵌入复杂编辑器:在单元格中嵌入复杂的编辑器,例如 QComboBox、QDateEdit 等,允许用户直接进行选择或输入。例如,在表格的某个单元格中嵌入一个下拉框,用户可以直接选择选项。
- 实现持续编辑:当需要用户持续编辑某个单元格时,可以使用持久编辑器。例如,在表格中嵌入一个 QLineEdit,用户可以随时修改内容。
- 动态控制编辑状态:在某些情况下,可能需要动态控制单元格的编辑状态。例如,根据某些条件决定是否打开持久编辑器。
示例代码:
#include
#include
#include
#include
#include
#include
#include
int main(int argc, char *argv[]) {
QApplication app(argc, argv);
// 创建一个窗口
QWidget window;
QVBoxLayout* layout = new QVBoxLayout(&window);
// 创建一个 2x2 的表格
QTableWidget* tableWidget = new QTableWidget(2, 2, &window);
layout->addWidget(tableWidget);
// 设置表格内容
for (int row = 0; row < 2; ++row) {
for (int col = 0; col < 2; ++col) {
QTableWidgetItem* item = new QTableWidgetItem(QString("Item %1,%2").arg(row).arg(col));
tableWidget->setItem(row, col, item);
}
}
// 在 (0, 0) 单元格中打开持久编辑器(QLineEdit)
QTableWidgetItem* item = tableWidget->item(0, 0);
tableWidget->openPersistentEditor(item);
// 在 (1, 1) 单元格中打开持久编辑器(QComboBox)
QComboBox* comboBox = new QComboBox(tableWidget);
comboBox->addItems({"Option 1", "Option 2", "Option 3"});
tableWidget->setCellWidget(1, 1, comboBox);
// 添加一个按钮,用于关闭持久编辑器
QPushButton* closeEditorButton = new QPushButton("Close Editor", &window);
layout->addWidget(closeEditorButton);
// 连接按钮点击信号到槽函数
QObject::connect(closeEditorButton, &QPushButton::clicked, [tableWidget, item]() {
tableWidget->closePersistentEditor(item);
});
// 显示窗口
window.show();
return app.exec();
}
5.获取单元格的列索引和行索引
QTableWidget::column(const QTableWidgetItem *item) 用于获取指定 QTableWidgetItem 所在的列索引。
函数原型:
int QTableWidget::column(const QTableWidgetItem *item) const;
QTableWidget::row(const QTableWidgetItem *item) 用于获取指定 QTableWidgetItem 所在的行索引。
函数原型:
int QTableWidget::row(const QTableWidgetItem *item) const;
示例代码:
#include
#include
#include
#include
int main(int argc, char *argv[]) {
QApplication app(argc, argv);
// 创建一个 3x3 的表格
QTableWidget tableWidget(3, 3);
tableWidget.setWindowTitle("QTableWidget Example");
// 设置表格内容
for (int row = 0; row < 3; ++row) {
for (int col = 0; col < 3; ++col) {
QTableWidgetItem* item = new QTableWidgetItem(QString("Item %1,%2").arg(row).arg(col));
tableWidget.setItem(row, col, item);
}
}
// 获取 (1, 2) 单元格的行列索引
QTableWidgetItem* item = tableWidget.item(1, 2);
if (item) {
int row = tableWidget.row(item); // 获取行索引
int col = tableWidget.column(item); // 获取列索引
qDebug() << "Item text:" << item->text();
qDebug() << "Row:" << row << "Column:" << col;
} else {
qDebug() << "Item not found!";
}
// 显示表格
tableWidget.show();
return app.exec();
}
6.获取表格中当前的列数和行数
QTableWidget::columnCount() 用于获取表格中当前的列数。
函数原型:
int QTableWidget::columnCount() const;
int QTableWidget::rowCount() 用于获取表格中当前的行数。
函数原型
int QTableWidget::rowCount() const;
示例代码:
#include
#include
#include
int main(int argc, char *argv[]) {
QApplication app(argc, argv);
// 创建一个 3x3 的表格
QTableWidget tableWidget(3, 3);
tableWidget.setWindowTitle("QTableWidget Example");
// 设置表格内容
for (int row = 0; row < tableWidget.rowCount(); ++row) {
for (int col = 0; col < tableWidget.columnCount(); ++col) {
QTableWidgetItem* item = new QTableWidgetItem(QString("Item %1,%2").arg(row).arg(col));
tableWidget.setItem(row, col, item);
}
}
// 获取表格的列数
int columns = tableWidget.columnCount();
int rows = tableWidget.rowCount();
qDebug() << "Column count:" << columns;
qDebug() << "rows count:" << rows;
// 显示表格
tableWidget.show();
return app.exec();
}
7.获取当前选中单元格的列索引
int QTableWidget::currentColumn() 用于获取当前选中单元格的列索引。
#include
#include
#include
int main(int argc, char *argv[]) {
QApplication app(argc, argv);
// 创建一个 3x3 的表格
QTableWidget tableWidget(3, 3);
tableWidget.setWindowTitle("QTableWidget Example");
// 设置表格内容
for (int row = 0; row < 3; ++row) {
for (int col = 0; col < 3; ++col) {
QTableWidgetItem* item = new QTableWidgetItem(QString("Item %1,%2").arg(row).arg(col));
tableWidget.setItem(row, col, item);
}
}
// 连接单元格点击信号到槽函数
QObject::connect(&tableWidget, &QTableWidget::cellClicked, [&tableWidget](int row, int col) {
qDebug() << "Cell clicked at row:" << row << "column:" << col;
qDebug() << "Current row:" << tableWidget.currentRow();
qDebug() << "Current column:" << tableWidget.currentColumn();
});
// 显示表格
tableWidget.show();
return app.exec();
}
8.获取当前选中单元格的项
QTableWidgetItem *QTableWidget::currentItem() 用于获取当前选中单元格的 QTableWidgetItem 对象。
#include
#include
#include
int main(int argc, char *argv[]) {
QApplication app(argc, argv);
// 创建一个 3x3 的表格
QTableWidget tableWidget(3, 3);
tableWidget.setWindowTitle("QTableWidget Example");
// 设置表格内容
for (int row = 0; row < 3; ++row) {
for (int col = 0; col < 3; ++col) {
QTableWidgetItem* item = new QTableWidgetItem(QString("Item %1,%2").arg(row).arg(col));
tableWidget.setItem(row, col, item);
}
}
// 连接单元格点击信号到槽函数
QObject::connect(&tableWidget, &QTableWidget::cellClicked, [&tableWidget](int row, int col) {
// 获取当前选中单元格的 QTableWidgetItem
QTableWidgetItem* item = tableWidget.currentItem();
if (item) {
qDebug() << "Cell clicked at row:" << row << "column:" << col;
qDebug() << "Current item text:" << item->text();
} else {
qDebug() << "No item selected!";
}
});
// 显示表格
tableWidget.show();
return app.exec();
}
1.插入数据
可以通过 setItem() 方法向表格中插入数据:
tableWidget->setItem(0, 0, new QTableWidgetItem("张三"));
tableWidget->setItem(0, 1, new QTableWidgetItem("25"));
tableWidget->setItem(0, 2, new QTableWidgetItem("北京"));
2.获取数据
QString name = tableWidget->item(0, 0)->text();
3.修改数据
直接修改 QTableWidgetItem 的内容即可:
tableWidget->item(0, 1)->setText("26");
1.设置单元格样式
可以通过 QTableWidgetItem 设置单元格的背景色、字体和对齐方式:
QTableWidgetItem* item = new QTableWidgetItem("居中");
item->setBackground(QBrush(Qt::yellow)); // 设置背景色
item->setTextAlignment(Qt::AlignCenter); // 设置对齐方式
tableWidget->setItem(0, 0, item);
2. 合并单元格
使用 setSpan() 方法可以合并单元格:
tableWidget->setSpan(0, 0, 1, 3); // 合并从 (0,0) 到 (0,2) 的单元格
3.禁用编辑
通过设置 QTableWidgetItem 的标志位,可以禁用单元格编辑:
item->setFlags(item->flags() & ~Qt::ItemIsEditable);
1.单元格点击事件
作用:
- 该信号在用户单击 QTableWidget 中的某个单元格时发出。
- 它通常用于响应用户的点击操作,例如选中单元格、显示详细信息或执行其他操作。
使用场景:
- 当你需要监听用户对 QTableWidget 中某个单元格的点击操作时,可以连接此信号到一个槽函数。
- 例如,用户单击某个单元格后,你可能需要高亮显示该单元格、更新界面状态或执行其他逻辑。
注意事项:
- 触发时机:当用户单击表格中的某个单元格时,cellClicked 信号会被触发。即使单击的是同一个单元格多次,每次单击都会触发该信号。
- 与 cellActivated 的区别:cellClicked 是用户单击单元格时触发的信号。cellActivated 是用户通过双击或按下 Enter 键激活单元格时触发的信号。
- 与 cellDoubleClicked 的区别:cellClicked 是单击单元格时触发的信号。cellDoubleClicked 是双击单元格时触发的信号。
- 与 itemClicked 的区别:cellClicked 是针对单元格的信号,参数是行和列索引。itemClicked 是针对 QTableWidgetItem 的信号,参数是一个 QTableWidgetItem 指针。
连接 cellClicked 信号,可以捕获单元格点击事件:
connect(tableWidget, &QTableWidget::cellClicked, [](int row, int col) {
qDebug() << "点击了行" << row << "列" << col;
});
2.单元格内容修改事件
作用:
- 该信号在单元格的内容(例如文本或数据)被修改时发出。
- 它通常用于监听单元格内容的变更,以便执行相应的操作。
使用场景:
- 当你需要监听 QTableWidget 中某个单元格内容的改变时,可以连接此信号到一个槽函数。
- 例如,当用户编辑单元格内容后,你可能需要更新数据模型、验证输入或执行其他操作。
连接 cellChanged 信号,可以捕获单元格内容修改事件:
connect(tableWidget, &QTableWidget::cellChanged, [](int row, int col) {
qDebug() << "内容修改为:" << tableWidget->item(row, col)->text();
});
注意事项:
- 触发时机:当单元格的内容被修改(例如用户编辑文本或通过代码设置新值)时,cellChanged 信号会被触发。如果单元格的内容没有实际改变(例如设置相同的值),信号可能不会触发。
- 与 itemChanged 的区别:cellChanged 是针对特定单元格的信号,参数是行和列索引。itemChanged 是针对 QTableWidgetItem 的信号,参数是一个 QTableWidgetItem 指针。
3.当鼠标光标进入表格的某个单元格时会触发事件
典型应用场景:
- 显示工具提示(ToolTip):当鼠标悬停在某个单元格上时,显示该单元格的详细信息或提示。
- 高亮显示:当鼠标进入某个单元格的区域时,高亮显示该单元格或其所在的行/列。
- 动态更新界面:根据鼠标悬停的单元格,动态更新界面上的其他控件或信息。
当用户将鼠标移动到 QTableWidget 的某个单元格上时,cellEntered 信号会被触发:
// 连接 cellEntered 信号到自定义槽函数
connect(tableWidget, &QTableWidget::cellEntered, this, &MyClass::onCellEntered);
// 自定义槽函数
void MyClass::onCellEntered(int row, int column) {
QTableWidgetItem *item = this->item(row, column);
if (item) {
qDebug() << "Mouse entered cell at row:" << row << "column:" << column;
qDebug() << "Cell text:" << item->text();
// 显示工具提示
tableWidget->setToolTip(item->text());
} else {
qDebug() << "No cell entered.";
}
}
注意事项:如果 QTableWidget 的 mouseTracking 属性未启用(默认是关闭的),则 cellEntered 信号只会在鼠标按下并移动时触发。如果需要实时跟踪鼠标移动,可以调用 setMouseTracking(true) 来启用鼠标跟踪功能。
4.激活某个单元格时被触发
void QTableWidget::cellActivated(int row, int column) 当用户激活某个单元格时会触发此信号。
函数原型:
void QTableWidget::cellActivated(int row, int column)
作用:
- 该信号在用户通过某种方式(例如双击单元格或按下 Enter 键)激活单元格时发出
- 它通常用于响应用户对单元格的交互操作。
使用场景:
- 当你需要监听用户对 QTableWidget 中某个单元格的激活操作时,可以连接此信号到一个槽函数
- 例如,用户双击某个单元格后,你可能需要弹出编辑窗口或执行其他操作。
// 连接 cellActivated 信号到自定义槽函数
connect(tableWidget, &QTableWidget::cellActivated, this, &MyClass::onCellActivated);
void MyClass::onCellActivated(int row, int column) {
qDebug() << "Cell activated at row:" << row << "column:" << column;
// 在这里添加处理逻辑,例如弹出编辑窗口或更新数据
}
注意事项:
- 激活方式:单元格的激活通常由用户双击单元格或按下 Enter 键触发。如果单元格是可编辑的,激活后可能会进入编辑模式。
- 与 cellClicked 的区别:cellActivated 是用户明确激活单元格时触发的信号。cellClicked 是用户单击单元格时触发的信号,不一定表示激活。
- 与 cellDoubleClicked 的区别:cellDoubleClicked 是用户双击单元格时触发的信号。cellActivated 可能由双击或按下 Enter 键触发,具体取决于平台和用户设置。
5.双击表格中的某个单元格时会触发事件
作用:
- 该信号在用户双击 QTableWidget 中的某个单元格时发出。
- 它通常用于响应用户的双击操作,例如进入编辑模式、打开详细信息对话框或执行其他操作
使用场景:
- 当你需要监听用户对 QTableWidget 中某个单元格的双击操作时,可以连接此信号到一个槽函数。
- 例如,用户双击某个单元格后,你可能需要进入编辑模式、弹出详细信息窗口或执行其他逻辑。
// 连接 cellDoubleClicked 信号到自定义槽函数
connect(tableWidget, &QTableWidget::cellDoubleClicked, this, &MyTableWidget::onCellDoubleClicked);
void MyTableWidget::onCellDoubleClicked(int row, int column) {
qDebug() << "Cell double-clicked at row:" << row << "column:" << column;
// 获取被双击的单元格内容
QTableWidgetItem *item = this->item(row, column);
if (item) {
qDebug() << "Cell content:" << item->text();
}
// 在这里添加处理逻辑,例如进入编辑模式或弹出对话框
}
6.按下表格中的某个单元格时触发事件
作用:当用户点击或按下 QTableWidget 中的某个单元格时,该信号会被发射。你可以连接这个信号到一个自定义的槽函数(slot),以便在单元格被按下时执行特定的操作。
// 连接 cellPressed 信号到自定义的槽函数
connect(tableWidget, &QTableWidget::cellPressed, this, &MyTableWidget::onCellPressed);
void MyTableWidget::onCellPressed(int row, int column) {
qDebug() << "Cell pressed at row:" << row << "column:" << column;
}
7.当前选中的单元格发生变化时触发事件
函数原型:
void QTableWidget::currentCellChanged(int currentRow, int currentColumn, int previousRow, int previousColumn)
参数:
- currentRow: 当前选中单元格的行索引(从 0 开始)。
- currentColumn: 当前选中单元格的列索引(从 0 开始)。
- previousRow: 之前选中单元格的行索引(如果没有之前选中的单元格,值为 -1)。
- previousColumn: 之前选中单元格的列索引(如果没有之前选中的单元格,值为 -1)。
作用:当用户通过点击、键盘导航或其他方式改变 QTableWidget 中当前选中的单元格时,该信号会被发射。你可以连接这个信号到一个自定义的槽函数,以便在选中单元格发生变化时执行特定的操作。
connect(tableWidget, &QTableWidget::currentCellChanged, this, &MyTableWidget::onCurrentCellChanged);
void MyTableWidget::onCurrentCellChanged(int currentRow, int currentColumn, int previousRow, int previousColumn) {
qDebug() << "Current cell changed to row:" << currentRow << "column:" << currentColumn;
qDebug() << "Previous cell was row:" << previousRow << "column:" << previousColumn;
}
8.当前选中的项(QTableWidgetItem)发生变化时触发事件
函数原型:
void QTableWidget::currentItemChanged(QTableWidgetItem *current, QTableWidgetItem *previous)
参数:
- current: 指向当前选中的 QTableWidgetItem 的指针。如果没有当前选中的项,该参数为 nullptr。
- previous: 指向之前选中的 QTableWidgetItem 的指针。如果没有之前选中的项,该参数为 nullptr。
作用:当用户通过点击、键盘导航或其他方式改变 QTableWidget 中当前选中的项时,该信号会被发射。你可以连接这个信号到一个自定义的槽函数,以便在选中项发生变化时执行特定的操作。
与 currentCellChanged 的区别:
- currentCellChanged 信号关注的是单元格的行和列索引的变化。
- currentItemChanged 信号关注的是具体的 QTableWidgetItem 对象的变化,因此可以访问项的文本、数据、样式等属性。
// 连接 currentItemChanged 信号到自定义的槽函数
connect(tableWidget, &QTableWidget::currentItemChanged, this, &MyTableWidget::onCurrentItemChanged);
void onCurrentItemChanged(QTableWidgetItem *current, QTableWidgetItem *previous) {
if (current) {
qDebug() << "Current item text:" << current->text();
} else {
qDebug() << "No current item selected.";
}
if (previous) {
qDebug() << "Previous item text:" << previous->text();
} else {
qDebug() << "No previous item selected.";
}
}
9.用户激活某个表格项(QTableWidgetItem)时触发事件
函数原型:
void QTableWidget::itemActivated(QTableWidgetItem *item)
参数:item: 指向被激活的 QTableWidgetItem 的指针。如果没有被激活的项,该参数为 nullptr。
作用:当用户通过双击或按下回车键等方式激活 QTableWidget 中的某个项时,该信号会被发射。你可以连接这个信号到一个自定义的槽函数,以便在项被激活时执行特定的操作。
与 itemClicked 和 itemDoubleClicked 的区别:
- itemClicked: 当用户单击某个项时触发。
- itemDoubleClicked: 当用户双击某个项时触发。
- itemActivated: 当用户通过双击或按下回车键等方式激活某个项时触发。它比 itemDoubleClicked 更通用,因为它不仅响应双击,还响应其他激活方式(如按下回车键)。
// 连接 itemActivated 信号到自定义的槽函数
connect(tableWidget, &QTableWidget::itemActivated, this, &MyTableWidget::onItemActivated);
void onItemActivated(QTableWidgetItem *item) {
if (item) {
qDebug() << "Item activated with text:" << item->text();
} else {
qDebug() << "No item activated.";
}
}
10.在表格项(QTableWidgetItem)的内容或状态发生变化时触发事件
函数原型:
void QTableWidget::itemChanged(QTableWidgetItem *item)
参数:item: 指向内容或状态发生变化的 QTableWidgetItem 的指针。
作用:当 QTableWidget 中的某个项的内容(如文本、图标等)或状态(如选中状态、编辑状态等)发生变化时,该信号会被发射。你可以连接这个信号到一个自定义的槽函数,以便在项发生变化时执行特定的操作。
触发时机:
- 当用户编辑项的内容(例如在单元格中输入文本)时。
- 当通过代码修改项的内容或状态(例如调用 setText()、setIcon() 等方法)时。
- 当项的选中状态、字体、颜色等属性发生变化时。
// 连接 itemChanged 信号到自定义的槽函数
connect(tableWidget, &QTableWidget::itemChanged, this, &MyTableWidget::onItemChanged);
void onItemChanged(QTableWidgetItem *item) {
if (item) {
qDebug() << "Item changed at row:" << item->row() << "column:" << item->column();
qDebug() << "New text:" << item->text();
} else {
qDebug() << "No item changed.";
}
}
11.用于在用户单击表格中的某个项(QTableWidgetItem)时触发事件
函数原型:
void QTableWidget::itemClicked(QTableWidgetItem *item)
参数:item: 指向被单击的 QTableWidgetItem 的指针。如果没有被单击的项,该参数为 nullptr。
作用:当用户单击 QTableWidget 中的某个项时,该信号会被发射。你可以连接这个信号到一个自定义的槽函数,以便在项被单击时执行特定的操作。
与 itemActivated 和 itemDoubleClicked 的区别:
- itemClicked: 当用户单击某个项时触发。
- itemDoubleClicked: 当用户双击某个项时触发。
- itemActivated: 当用户通过双击或按下回车键等方式激活某个项时触发。
//连接 itemClicked 信号到自定义的槽函数
connect(tableWidget, &QTableWidget::itemClicked, this, &MyTableWidget::onItemClicked);
void onItemClicked(QTableWidgetItem *item) {
if (item) {
qDebug() << "Item clicked at row:" << item->row() << "column:" << item->column();
qDebug() << "Item text:" << item->text();
} else {
qDebug() << "No item clicked.";
}
}
12.用于在用户双击表格中的某个项(QTableWidgetItem)时触发事件
函数原型:
void QTableWidget::itemDoubleClicked(QTableWidgetItem *item)
作用:当用户双击 QTableWidget 中的某个项时,该信号会被发射。你可以连接这个信号到一个自定义的槽函数,以便在项被双击时执行特定的操作。
// 连接 itemDoubleClicked 信号到自定义的槽函数
connect(tableWidget, &QTableWidget::itemDoubleClicked, this, &MyTableWidget::onItemDoubleClicked);
void onItemDoubleClicked(QTableWidgetItem *item) {
if (item) {
qDebug() << "Item double-clicked at row:" << item->row() << "column:" << item->column();
qDebug() << "Item text:" << item->text();
} else {
qDebug() << "No item double-clicked.";
}
}
13.用于在鼠标光标进入某个表格项(QTableWidgetItem)的区域时触发事件
函数原型:
void QTableWidget::itemEntered(QTableWidgetItem *item)
作用:当用户将鼠标光标移动到 QTableWidget 中的某个项上时,该信号会被发射。你可以连接这个信号到一个自定义的槽函数,以便在鼠标进入项的区域时执行特定的操作。
典型应用场景:
- 显示工具提示(ToolTip):当鼠标悬停在某个项上时,显示该项的详细信息或提示。
- 高亮显示:当鼠标进入某个项的区域时,高亮显示该项或其所在的行/列
- 态更新界面:根据鼠标悬停的项,动态更新界面上的其他控件或信息。
// 连接 itemEntered 信号到自定义的槽函数
connect(tableWidget, &QTableWidget::itemEntered, this, &MyTableWidget::onItemEntered);
void onItemEntered(QTableWidgetItem *item) {
if (item) {
qDebug() << "Mouse entered item at row:" << item->row() << "column:" << item->column();
qDebug() << "Item text:" << item->text();
// 显示工具提示
tableWidget->setToolTip(item->text());
} else {
qDebug() << "No item entered.";
}
}
注意事项:如果 QTableWidget 的 mouseTracking 属性未启用(默认是关闭的),则 itemEntered信号只会在鼠标按下并移动时触发。如果需要实时跟踪鼠标移动,可以调用 setMouseTracking(true) 来启用鼠标跟踪功能。
14.用户按下鼠标按钮(例如左键或右键)并位于某个表格项(QTableWidgetItem)上时触发事件
函数原型:
void QTableWidget::itemPressed(QTableWidgetItem *item)
作用:当用户在 QTableWidget 中的某个项上按下鼠标按钮时,该信号会被发射。你可以连接这个信号到一个自定义的槽函数,以便在项被按下时执行特定的操作。
典型应用场景:
- 自定义鼠标按下行为:例如,在按下某项时显示上下文菜单或执行特定操作。
- 实现拖放功能:在按下某项时开始拖放操作。
- 记录按下事件:用于记录用户交互行为或触发某些逻辑。
// 连接 itemPressed 信号到自定义的槽函数
connect(tableWidget, &QTableWidget::itemPressed, this, &MyTableWidget::onItemPressed);
void onItemPressed(QTableWidgetItem *item) {
if (item) {
qDebug() << "Item pressed at row:" << item->row() << "column:" << item->column();
qDebug() << "Item text:" << item->text();
} else {
qDebug() << "No item pressed.";
}
}
注意事项:
- 与 itemClicked 的区别:itemPressed 是在鼠标按钮按下时触发,而 itemClicked 是在鼠标按钮按下并释放后触发。如果你需要在鼠标按下时立即执行某些操作,可以使用
itemPressed;如果你需要在完整的点击操作(按下并释放)后执行操作,可以使用 itemClicked。- 与 itemDoubleClicked 的区别:itemDoubleClicked 是在用户双击某项时触发,而 itemPressed 是在按下鼠标按钮时触发,无论是否双击。
15.用于在表格中的选中项(QTableWidgetItem)发生变化时触发事件
函数原型:
void QTableWidget::itemSelectionChanged()
作用:当用户通过点击、键盘导航或其他方式改变 QTableWidget 中的选中项时,该信号会被发射。你可以连接这个信号到一个自定义的槽函数,以便在选中项发生变化时执行特定的操作。
// 连接 itemSelectionChanged 信号到自定义的槽函数
connect(m_table_list, &QTableWidget::itemSelectionChanged, this, &MainWindow::onItemSelectionChanged);
void onItemSelectionChanged() {
// 获取当前选中的所有项
QList<QTableWidgetItem*> selectedItems = m_table_list->selectedItems();
qDebug() << "Selected items:";
for (QTableWidgetItem *item : selectedItems) {
qDebug() << "Row:" << item->row() << "Column:" << item->column() << "Text:" << item->text();
}
}
与 currentItemChanged 的区别:
- itemSelectionChanged 是在选中项集合发生变化时触发,适用于多选场景。
- currentItemChanged 是在当前焦点项发生变化时触发,适用于单选场景。
#include "mainwindow.h"
#define TABLE_HEADER_STYLE "QHeaderView::section {border-top: 1px solid #d8d8d8; border-bottom: 1px solid #d8d8d8; \
border-right: 1px solid #d8d8d8; background: #f6f7f9; color: #333333; font-size: 16px;}"
#define HSCROLL_BAR_STYLE "QScrollBar {background: transparent; height: 10px; margin: 0px;}" \
"QScrollBar::handle {background: #dfdfe1; border-radius: 3px; margin: 0px;}" \
"QScrollBar::handle:hover {background: lightgray;}" \
"QScrollBar::handle:pressed {background: #dfdfe1;}" \
"QScrollBar::sub-page {background: transparent;}" \
"QScrollBar::add-page {background: transparent;}" \
"QScrollBar::sub-line {background: transparent; width: 0px;}" \
"QScrollBar::add-line {background: transparent; width: 0px;}"
#define VSCROLL_BAR_STYLE "QScrollBar {background: transparent; width: 10px; margin: 0px;}" \
"QScrollBar::handle {background: #dfdfe1; border-radius: 3px; margin: 0px;}" \
"QScrollBar::handle:hover {background: lightgray;}" \
"QScrollBar::handle:pressed {background: #dfdfe1;}" \
"QScrollBar::sub-page {background: transparent;}" \
"QScrollBar::add-page {background: transparent;}" \
"QScrollBar::sub-line {background: transparent; height: 0px;}" \
"QScrollBar::add-line {background: transparent; height: 0px;}"
MainWindow::MainWindow(QWidget *parent)
: QWidget(parent)
{
this->setFixedSize(800, 500);
m_btn_load_data = new QPushButton("加载", this);
connect(m_btn_load_data, &QPushButton::clicked, this, &MainWindow::on_btn_load_data_clicked);
m_btn_load_data->setGeometry(24, 10, 100, 30);
m_btn_delete_data = new QPushButton("删除", this);
connect(m_btn_delete_data, &QPushButton::clicked, this, &MainWindow::on_btn_delete_data_clicked);
m_btn_delete_data->setGeometry(130, 10, 100, 30);
m_table_list = new QTableWidget(0, 7, this);
m_table_list->setStyleSheet("QTableWidget {color: #333333; font-size: 16px;}");
m_table_list->horizontalHeader()->setStyleSheet(TABLE_HEADER_STYLE);
m_table_list->horizontalScrollBar()->setStyleSheet(HSCROLL_BAR_STYLE);
m_table_list->verticalScrollBar()->setStyleSheet(VSCROLL_BAR_STYLE);
m_table_list->setGeometry(24, 70, 750, 400);
m_table_list->horizontalHeader()->setFixedHeight(36);
m_table_list->verticalHeader()->setFixedWidth(36);
m_table_list->setSelectionMode(QAbstractItemView::NoSelection);
m_table_list->setEditTriggers(QAbstractItemView::NoEditTriggers);
m_table_list->setFocusPolicy(Qt::NoFocus);
m_table_list->setFrameShape(QFrame::NoFrame);
m_table_list->setMouseTracking(true);
connect(m_table_list, &QTableWidget::cellEntered, this, &MainWindow::solt_cell_entered);
m_table_list->verticalHeader()->hide();
m_table_list->horizontalHeader()->setSectionsClickable(false);
m_table_list->horizontalHeader()->setStretchLastSection(true);
m_table_list->setColumnWidth(0, 36);
m_table_list->setColumnWidth(1, 60);
m_table_list->setColumnWidth(2, 120);
m_table_list->setColumnWidth(3, 120);
m_table_list->setColumnWidth(4, 120);
m_table_list->setColumnWidth(5, 120);
m_table_list->setColumnWidth(6, 120);
m_table_list->setColumnWidth(7, 100);
QWidget *fix_line = new QWidget(m_table_list);
fix_line->setStyleSheet("QWidget {border: 1px solid #d8d8d8;}");
fix_line->setGeometry(0, 0, 1, 36);
QStringList column_name_list;
column_name_list << "" << "序号" << "游戏" << "游戏价格" << "游戏类型" << "备注" << "操作";
m_table_list->setHorizontalHeaderLabels(column_name_list);
m_table_check = new QCheckBox(m_table_list);
connect(m_table_check, SIGNAL(clicked()), this, SLOT(table_check_clicked()));
m_table_check->setGeometry(10, 10, 20, 20);
QJsonArray json_array;
QJsonObject json_object1;
json_object1.insert("game", "刺客信条起源");
json_object1.insert("price", "298元");
json_object1.insert("type", "PVE");
json_object1.insert("remarks", "开放世界");
json_array.append(json_object1);
QJsonObject json_object2;
json_object2.insert("game", "刺客信条奥德赛");
json_object2.insert("price", "298元");
json_object2.insert("type", "PVE");
json_object2.insert("remarks", "开放世界");
json_array.append(json_object2);
QJsonObject json_object3;
json_object3.insert("game", "只狼:影逝二度");
json_object3.insert("price", "268元");
json_object3.insert("type", "PVE");
json_object3.insert("remarks", "魂类");
json_array.append(json_object3);
QJsonObject json_object4;
json_object4.insert("game", "英雄联盟");
json_object4.insert("price", "免费");
json_object4.insert("type", "PVP");
json_object4.insert("remarks", "MOBA");
json_array.append(json_object4);
QJsonObject json;
json.insert("game_list", QJsonValue(json_array));
m_json_data = QJsonDocument(json).toJson(QJsonDocument::Compact);
}
MainWindow::~MainWindow()
{
}
void MainWindow::table_check_clicked()
{
QCheckBox *check = static_cast<QCheckBox *>(sender());
int state = check->checkState();
for (int i = 0; i < m_table_list->rowCount(); i++) {
QCheckBox *temp = (QCheckBox *)m_table_list->cellWidget(i, 0);
if (state == Qt::Checked) {
temp->setCheckState(Qt::Checked);
} else {
temp->setCheckState(Qt::Unchecked);
}
}
}
void MainWindow::table_item_check_clicked()
{
QCheckBox *check = static_cast<QCheckBox *>(sender());
int state = check->checkState();
if (state == Qt::Unchecked) {
m_table_check->setCheckState(Qt::Unchecked);
} else {
for (int i = 0; i < m_table_list->rowCount(); i++) {
QCheckBox *temp = (QCheckBox *)m_table_list->cellWidget(i, 0);
if (temp->checkState() == Qt::Unchecked) {
return;
}
}
m_table_check->setCheckState(Qt::Checked);
}
}
void MainWindow::buy_button_clicked()
{
QPushButton *btn_buy = static_cast<QPushButton *>(sender()) ;
int row = btn_buy->property("row").toInt();
QString game = m_table_list->item(row, 2)->text();
QString price = m_table_list->item(row, 3)->text();
QString type = m_table_list->item(row, 4)->text();
QString remarks = m_table_list->item(row, 5)->text();
qDebug() << "game:" << game << "price:" << price << "type:" << type << "remarks:" << remarks;
}
void MainWindow::on_btn_load_data_clicked()
{
QJsonParseError json_parse;
QJsonDocument json_doucment = QJsonDocument::fromJson(m_json_data, &json_parse);
if (json_parse.error == QJsonParseError::NoError) {
if (json_doucment.isObject()) {
QJsonObject json_object = json_doucment.object();
qDebug() << "json_object:" << json_object;
QJsonArray json_array = json_object.take("game_list").toArray();
m_table_check->setCheckState(Qt::Unchecked);
for (int i = 0; i < m_table_list->rowCount(); i++) {
m_table_list->setRowHidden(i, false);
}
m_table_list->clearContents();
m_table_list->setRowCount(json_array.size());
for (int i = 0; i < json_array.size(); i++) {
QJsonObject mac_obj = json_array[i].toObject();
QString game = mac_obj.take("game").toString();
QString price = mac_obj.take("price").toString();
QString type = mac_obj.take("type").toString();
QString remarks = mac_obj.take("remarks").toString();
/* 复选框 */
QCheckBox *check = new QCheckBox(m_table_list);
connect(check, SIGNAL(clicked()), this, SLOT(table_item_check_clicked()));
check->setStyleSheet("QCheckBox {padding-top: 10px; padding-left: 10px;}");
check->setFixedSize(30, 30);
check->setProperty("row", i);
m_table_list->setCellWidget(i, 0, check);
/* 表格内容 */
m_table_list->setItem(i, 1, new QTableWidgetItem(QString::number(i + 1)));
m_table_list->setItem(i, 2, new QTableWidgetItem(game));
m_table_list->setItem(i, 3, new QTableWidgetItem(price));
m_table_list->setItem(i, 4, new QTableWidgetItem(type));
m_table_list->setItem(i, 5, new QTableWidgetItem(remarks));
for (int j = 1; j <= 5; j++) {
m_table_list->item(i, j)->setTextAlignment(Qt::AlignCenter);
}
/* 操作栏 */
QWidget *widget_op = new QWidget;
QHBoxLayout *layout_op = new QHBoxLayout;
layout_op->setAlignment(Qt::AlignCenter);
layout_op->setSpacing(5);
layout_op->setSpacing(0);
layout_op->setMargin(0);
QPushButton *btn_op = new QPushButton("购买", m_table_list);
connect(btn_op, SIGNAL(clicked()), this, SLOT(buy_button_clicked()));
btn_op->setStyleSheet("QPushButton {border: 1px solid #067EFF; border-radius: 4px; padding-top: -3px; background-color: #ffffff; color: #067EFF; font-size: 16px;}"
"QPushButton:hover {background-color: #067EFF; color: #ffffff;}"
"QPushButton:pressed {background-color: #ffffff; color: #067EFF;}");
btn_op->setFixedSize(55, 25);
btn_op->setProperty("row", i);
layout_op->addWidget(btn_op);
widget_op->setLayout(layout_op);
m_table_list->setCellWidget(i, 6, widget_op);
}
}
}
}
void MainWindow::on_btn_delete_data_clicked()
{
for (int i = 0; i < m_table_list->rowCount(); i++) {
QCheckBox *temp = (QCheckBox *)m_table_list->cellWidget(i, 0);
if (temp->checkState() == Qt::Checked) {
int row = temp->property("row").toInt();
QString game = m_table_list->item(row, 2)->text();
QString price = m_table_list->item(row, 3)->text();
QString type = m_table_list->item(row, 4)->text();
QString remarks = m_table_list->item(row, 5)->text();
qDebug() << "game:" << game << "price:" << price << "type:" << type << "remarks:" << remarks;
}
}
}
void MainWindow::solt_cell_entered(int row, int column)
{
if (column != 2) {
return;
}
QTableWidgetItem *item = m_table_list->item(row, column);
if (item == NULL) {
return;
}
QToolTip::showText(QCursor::pos(), item->text());
}