在QTableWidget中获取QCheckBox的单元格位置

Get cell position of QCheckBox in QTableWidget

本文关键字:单元格 位置 QCheckBox 获取 QTableWidget      更新时间:2023-10-16

我有一个QTableWidget,在不同的列中有不同类型的单元格小部件,有多个列显示复选框

我想把QCheckBox的stateChanged信号与我的一个插槽连接起来,这样我就可以在我的模型中相应地设置数据

问题是,当用户更改QCheckBox状态时,QTableWidget的当前行不一定会更改

因此,我正在考虑继承QCheckBox并添加用于保存行和列信息的变量。这是个好方法吗?当我使用UI元素存储数据时,如果有什么问题的话。

我不需要创建额外的类,而是将小部件的行和列存储在映射中:

class YourWidgetWithTable
{
public:
    void foo()
    {
        //when you add cell widgets, do something like this:
        QCheckBox * b = new QCheckBox();
        tableWidget->setCellWidget(row, col, b);
        _widgetCells[b] = QPoint(row, col);
        connect(b, &QCheckBox::stateChanged, this, &YourWidgetWithTable::checkboxStateChanged);
        //if for whatever reason you are removing a checkbox from the table, don't forget to remove it from the map as well.
    }
public slots:
    void checkboxStateChanged(int)
    {
        //in your slot, you can now get the row and col like so:
        QCheckBox * box = dynamic_cast<QCheckBox*>(sender());
        QPoint rowAndColumn = _widgetCells[box];
    }
private:
    QMap<QCheckBox*, QPoint> _widgetCells; //QPoint for storing the row and column
}

当然,在没有dynamic_cast的情况下,也可以使用QObject*指针来执行同样的操作。

这只是我想到的第一个想法。我会将我所有的QCheckBox连接到同一个插槽(循环使用它们或在创建时(,然后当插槽执行时,我会得到它的调用者,它将是QCheckBox,我会获得它的父对象,它将成为它所在的单元格。

如果您坚持使用setCellWidget,并且您使用的是C++11,则使用lambda表达式进行连接。这将发挥作用:

void MainWindow::setupCheckboxes() {
     for (int i=1; i<=tableWidget->rowCount(); ++i) {
         QCheckBox *checkbox = new QCheckBox();
         ... // setup checkbox
         tableWidget->setCellWidget(i, kSomeColumnIndex, checkbox);
         connect(checkbox, &QAbstractButton::toggled, [this, i](bool checked) {
              this->stateOfRowHasChanged(i, checked);
         });
     }
}
void MainWindow::stateOfRowHasChanged(int row, bool checked) {
    // update item model
    QTableWidgetItem *item = tableWidget->item(row, kSomeColumnIndex);
    item->setData(Qt::CheckStateRole, checked?Qt::Checked:Qt::Unchecked);
     ... 
}

如果你不喜欢lambdas,请将复选框连接到这样的插槽:

void MainWindow::checkboxStateHasChenged(bool checked) {
     QCheckBox *checkbox = qobject_cast<QCheckBox *>(sender());
     if (checkbox) {
         QTableWidgetItem *item = tableWidget->itemAt(tableWidget->mapFrom(checkbox, QPos()));
         if (item) {
             item->setData(Qt::CheckStateRole, checked?Qt::Checked:Qt::Unchecked);
             ...
         }
     }
}

你做错了什么。你没有显示代码,所以很难说到底出了什么问题(我只是怀疑(。

无论如何,这就是MVC模式。所以,如果你想观察状态的变化,你必须观察数据模型的变化。您应该连接以执行dataChanged(还有其他更方便的信号QTableWidget::cellChanged(。数据可通过model((或更多获得。

使用数据模型更重要的是,您可以在表视图中设置复选默认复选框(不必手动添加(。

代码示例:

QTableWidgetItem *item = new QTableWidgetItem(tr("Somthing"));
item->setFlags(Qt::ItemIsUserCheckable|Qt::ItemIsEnabled|Qt::ItemNeverHasChildren);
tableWidget->setItem(row, column, item); // or add or whatever to add this item to widget and its model
connect(tableWidget->model(), SIGNAL(dataChanged(QModelIndex,QModelIndex,QVector<int>)), 
        this, SLOT(dataWasChanged(QModelIndex,QModelIndex,QVector<int>)));
// or
connect(tableWidget, SIGNAL(cellChanged(int, int)),
        this, SLOT(cellWasChanged(int, int)));
QPoint pos = tableWidget->mapFromGlobal(QCursor::pos());
QTableWidgetItem* item = tableWidget->item(tableWidget->indexAt(pos).row() - 1 , 0);

一旦你得到了物品,你就得到了位置。