Qt开发:QTableWidget的介绍和使用

文章目录

    • 一、QTableWidget的简介
    • 二、QTableWidget的基本用法
    • 三、QTableWidget的数据操作
    • 四、QTableWidget的样式与交互
    • 五、QTableWidget的信号与事件
    • 六、QTableWidget的完整代码示例

一、QTableWidget的简介

QTableWidget 是 Qt 提供的一个基于项的表格控件,继承自 QTableView。它允许开发者以行列形式展示和编辑数据,支持表头、单元格合并、样式定制等功能。与 QTableView 相比,QTableWidget 更加简单易用,适合快速开发小型表格应用。

二、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();
}

三、QTableWidget的数据操作

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");

四、QTableWidget的样式与交互

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);

五、QTableWidget的信号与事件

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 是在当前焦点项发生变化时触发,适用于单选场景。

六、QTableWidget的完整代码示例

#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());

}

效果展示:
Qt开发:QTableWidget的介绍和使用_第1张图片

你可能感兴趣的:(Qt初阶教程,qt)