Reputation: 517
I have a QTableWidget with different types of cell widget at different columns, having multiple columns showing checkboxes.
I want to connect the stateChanged signal of QCheckBox with one of my slots so that i can set the data correspondingly in my model.
The problem is when a QCheckBox state is changed by the user the current row of QTableWidget does not change necessarily.
So I am considering inheriting the QCheckBox and add variables for holding the row and column information. Is this a good method? What is the problem, if any, when I use the UI elements to store data.
Upvotes: 1
Views: 2899
Reputation: 29
QPoint pos = tableWidget->mapFromGlobal(QCursor::pos());
QTableWidgetItem* item = tableWidget->item(tableWidget->indexAt(pos).row() - 1 , 0);
Once you get the item, you get the position.
Upvotes: 0
Reputation: 38181
If you insist on using setCellWidget and you are using C++11 than do connections using lambda expressions. This will do the trick:
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);
...
}
If you do not like lambdas, than connect check-boxes to such slot:
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);
...
}
}
}
Upvotes: 1
Reputation: 38181
You are doing something terribly wrong. You didn't show the code so it is hard to say what is exactly wrong (I'm just suspecting).
Anyway this is MVC pattern. So if you want observe state changes you have to observe changes of data model. You should connect to do dataChanged (there is also other more convenient signal QTableWidget::cellChanged). Data is available by model() or more .
What is more important using data model you can set up check default check boxes in table view (you don't have to add them manually).
Code sample:
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)));
Upvotes: 0
Reputation: 29976
I would do it without making an additional class, but storing the widget's row and column in a map:
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
}
You can do the same without dynamic_cast
, using QObject*
pointers, of course.
Upvotes: 1
Reputation: 1354
This is just the first Idea crossed my mind. I would connect all my QCheckBox to the same slot (Looping through them or in the moment of creation) then when the slot gets executed I will get its caller which will be the QCheckBox and I will get its parent which will be the cell it's in.
Upvotes: 1