Kwok112 发表于 2024-11-14 09:45

Qt中QTableWidget自定义表格

本帖最后由 Kwok112 于 2024-11-14 10:39 编辑

需求:需要实现一个表格,每一个单元格作为一个独立的个体来代表某些东西,当触发操作时该单元格边框颜色要做出相应修改,同时保留其选中状态等一系列基础操作、
目前我是可以通过QList<QTableWidgetItem*> selectedItems = tableWidget->selectedItems();拿到被选中的单元格,想通过样式表的方式来修改此单元格的边框颜色但是感觉会很麻烦又不好单独操作使用设置背景颜色的方法如下
for (QTableWidgetItem *item : selectedItems) {
      int row = item->row();
      int column = item->column();
      qDebug() << "Row:" << row << "Column:" << column;
      item->setBackground(QColor("#FF0000")); // 红色背景色

    }
但是此方法在切换不同单元格时会取消设置,不能保存我当前设置的背景颜色,只能在我点击的时候绘制红色边框切换自动取消。
想问:能通过何种方法才能单独设置某一个单元格的边框颜色并保留,此操作需要频繁操作,同时针对触发的信号不同设置不同的边框颜色


目前通过添加自定义委托类重新绘制边框实现了该效果

Kwok112 发表于 2024-11-15 16:58

#include <QApplication>
#include <QWidget>
#include <QTableWidget>
#include <QTableWidgetItem>
#include <QLabel>
#include <QVBoxLayout>
#include <QGridLayout>
#include <QDebug>
#include <QObject>
#include <QStyledItemDelegate>
#include <QPainter>
#include <QMap>

// 创建自定义委托类
class CustomDelegate : public QStyledItemDelegate {
public:
    CustomDelegate(QObject *parent = nullptr) : QStyledItemDelegate(parent) {}

    // 设置特定单元格的边框颜色
    void setCellBorderColor(const QModelIndex &index, const QColor &color) {
      cellBorderColors = color; // 使用字典存储每个单元格的颜色
    }

    void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const override {
      // 绘制单元格内容
      QStyledItemDelegate::paint(painter, option, index);

      // 检查当前单元格是否有自定义边框颜色
       QColor borderColor = QColor(0, 0, 0, 0); // 默认边框颜色为透明
      if (cellBorderColors.contains(index)) {
            borderColor = cellBorderColors; // 获取自定义颜色
      }

      // 设置边框颜色和宽度
      painter->setPen(QPen(borderColor, 2)); // 使用指定的边框颜色

      // 获取矩形并绘制边框
      QRect rect = option.rect; // 获取矩形
      painter->drawRect(rect); // 绘制边框
    }

private:
    QMap<QModelIndex, QColor> cellBorderColors; // 存储每个单元格的边框颜色
};

class MyTableWidget : public QWidget {
public:
    MyTableWidget(int _numOfChannel, int _column, QWidget *parent = nullptr)
      : QWidget(parent), numOfChannel(_numOfChannel), column(_column), delegate(new CustomDelegate(this)) // 确保委托的生命周期
    {
      layout = new QVBoxLayout(this);

      titleLabel = new QLabel("Title");
      titleLabel->setAlignment(Qt::AlignCenter);
      titleLabel->setStyleSheet("font-size: 24pt; background-color: #D3D3D3; font-weight: bold;");
      layout->addWidget(titleLabel);

      tableWidget = new QTableWidget(numOfChannel / column, column, this); // 设置行数和列数
      layout->addWidget(tableWidget);
      tableWidget->setFocusPolicy(Qt::NoFocus);

      // 设置表格的行和列标题
      QStringList rowLabels;
      QStringList columnLabels;
      for (int i = 1; i <= column; ++i) {
            columnLabels << QString::number(i);
      }
      for (int i = 1; i <= numOfChannel / column; ++i) {
            rowLabels << QString::number(i);
      }
      tableWidget->setVerticalHeaderLabels(rowLabels);
      tableWidget->setHorizontalHeaderLabels(columnLabels);

      // 填充表格数据
      for (int row = 0; row < tableWidget->rowCount(); ++row) {
            for (int column = 0; column < tableWidget->columnCount(); ++column) {
                QTableWidgetItem *item = new QTableWidgetItem;
                item->setText(QString::number(row * 16 + column + 1));
                tableWidget->setItem(row, column, item);
            }
      }

      // 设置表格样式
      tableWidget->setStyleSheet("QTableWidget {"
                                    "gridline-color: #FFFFFF;"
                                    "border: 0px solid black;"
                                    "}"
                                    "QTableWidget::item {"
                                    "padding: 2px;"
                                    "background-color: #D3D3D3;"
                                    "border: 1px solid #FFFFFF;"
                                    "}"
                                    "QTableWidget::item:selected {"
                                    "background-color: #007ae6;"
                                    "}");

      // 设置委托
      tableWidget->setItemDelegate(delegate);

      // 连接信号与槽
      connect(tableWidget, &QTableWidget::itemSelectionChanged, this, &MyTableWidget::onSelectionChanged);
    }

    void setLabelTitle(QString titleName) {
      titleLabel->setText(titleName);
    }

    void setColumnNumber(int numOfChannel, int column) {
      tableWidget->setRowCount(numOfChannel / column);
      tableWidget->setColumnCount(column);
    }

private slots:
    void onSelectionChanged() {
      QList<QTableWidgetItem*> selectedItems = tableWidget->selectedItems();
      qDebug() << "Selected items:";
      for (QTableWidgetItem *item : selectedItems) {
            int row = item->row();
            int column = item->column();
            qDebug() << "Row:" << row << "Column:" << column;
            delegate->setCellBorderColor(tableWidget->model()->index(row, column), QColor(32, 33, 36)); // 设置为绿色
      }
      tableWidget->update(); // 确保表格更新以重新绘制
    }

private:
    QTableWidget *tableWidget;
    QLabel *titleLabel;
    QVBoxLayout *layout;
    int numOfChannel;
    int column;
    CustomDelegate *delegate; // 委托作为成员变量
};

int main(int argc, char *argv[]) {
    QApplication a(argc, argv);

    QWidget container;
    QGridLayout *gridLayout = new QGridLayout(&container);
    for (int i = 0; i < 8; ++i) {
      MyTableWidget *myTableWidget = new MyTableWidget(128, 8);
      gridLayout->addWidget(myTableWidget, i / 4, i % 4); // 将八个实例分布到2x4的网格中
    }

    container.setLayout(gridLayout);
    container.setWindowTitle("Multiple Table Widgets");
    container.resize(800, 600); // 设置窗口大小
    container.show();

    return a.exec();
}

Kwok112 发表于 2024-11-15 16:59

// 创建自定义委托类
class CustomDelegate : public QStyledItemDelegate {
public:
    CustomDelegate(QObject *parent = nullptr) : QStyledItemDelegate(parent) {}

    // 设置特定单元格的边框颜色
    void setCellBorderColor(const QModelIndex &index, const QColor &color) {
      cellBorderColors = color; // 使用字典存储每个单元格的颜色
    }

    void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const override {
      // 绘制单元格内容
      QStyledItemDelegate::paint(painter, option, index);

      // 检查当前单元格是否有自定义边框颜色
       QColor borderColor = QColor(0, 0, 0, 0); // 默认边框颜色为透明
      if (cellBorderColors.contains(index)) {
            borderColor = cellBorderColors; // 获取自定义颜色
      }

      // 设置边框颜色和宽度
      painter->setPen(QPen(borderColor, 2)); // 使用指定的边框颜色

      // 获取矩形并绘制边框
      QRect rect = option.rect; // 获取矩形
      painter->drawRect(rect); // 绘制边框
    }

private:
    QMap<QModelIndex, QColor> cellBorderColors; // 存储每个单元格的边框颜色
};class MyTableWidget : public QWidget {
public:
    MyTableWidget(int _numOfChannel, int _column, QWidget *parent = nullptr)
      : QWidget(parent), numOfChannel(_numOfChannel), column(_column), delegate(new CustomDelegate(this)) // 确保委托的生命周期
    {
      layout = new QVBoxLayout(this);

      titleLabel = new QLabel("Title");
      titleLabel->setAlignment(Qt::AlignCenter);
      titleLabel->setStyleSheet("font-size: 24pt; background-color: #D3D3D3; font-weight: bold;");
      layout->addWidget(titleLabel);

      tableWidget = new QTableWidget(numOfChannel / column, column, this); // 设置行数和列数
      layout->addWidget(tableWidget);
      tableWidget->setFocusPolicy(Qt::NoFocus);

      // 设置表格的行和列标题
      QStringList rowLabels;
      QStringList columnLabels;
      for (int i = 1; i <= column; ++i) {
            columnLabels << QString::number(i);
      }
      for (int i = 1; i <= numOfChannel / column; ++i) {
            rowLabels << QString::number(i);
      }
      tableWidget->setVerticalHeaderLabels(rowLabels);
      tableWidget->setHorizontalHeaderLabels(columnLabels);

      // 填充表格数据
      for (int row = 0; row < tableWidget->rowCount(); ++row) {
            for (int column = 0; column < tableWidget->columnCount(); ++column) {
                QTableWidgetItem *item = new QTableWidgetItem;
                item->setText(QString::number(row * 16 + column + 1));
                tableWidget->setItem(row, column, item);
            }
      }

      // 设置表格样式
      tableWidget->setStyleSheet("QTableWidget {"
                                    "gridline-color: #FFFFFF;"
                                    "border: 0px solid black;"
                                    "}"
                                    "QTableWidget::item {"
                                    "padding: 2px;"
                                    "background-color: #D3D3D3;"
                                    "border: 1px solid #FFFFFF;"
                                    "}"
                                    "QTableWidget::item:selected {"
                                    "background-color: #007ae6;"
                                    "}");

      // 设置委托
      tableWidget->setItemDelegate(delegate);

      // 连接信号与槽
      connect(tableWidget, &QTableWidget::itemSelectionChanged, this, &MyTableWidget::onSelectionChanged);
    }

    void setLabelTitle(QString titleName) {
      titleLabel->setText(titleName);
    }

    void setColumnNumber(int numOfChannel, int column) {
      tableWidget->setRowCount(numOfChannel / column);
      tableWidget->setColumnCount(column);
    }

private slots:
    void onSelectionChanged() {
      QList<QTableWidgetItem*> selectedItems = tableWidget->selectedItems();
      qDebug() << "Selected items:";
      for (QTableWidgetItem *item : selectedItems) {
            int row = item->row();
            int column = item->column();
            qDebug() << "Row:" << row << "Column:" << column;
            delegate->setCellBorderColor(tableWidget->model()->index(row, column), QColor(32, 33, 36)); // 设置为绿色
      }
      tableWidget->update(); // 确保表格更新以重新绘制
    }

private:
    QTableWidget *tableWidget;
    QLabel *titleLabel;
    QVBoxLayout *layout;
    int numOfChannel;
    int column;
    CustomDelegate *delegate; // 委托作为成员变量
};
页: [1]
查看完整版本: Qt中QTableWidget自定义表格