Swap rows QTableWidget
-
I'm working on a QTableWidget :
I'm trying to make it possible to rearrange the rows with those 'up' 'down' buttons that I just added, or even better by drag and drop.
I have seen many post about this, and no obvious answers. It is weird it feels like an extremely basic task for a table yet I couldn't find a solution yet.
I tried the following :for (int i = 0; i < columnCount; i++) { QTableWidgetItem* sourceItem = ui->workbenchTable->takeItem(rowIndex, i); QTableWidgetItem* destinationItem = ui->workbenchTable->takeItem(rowIndex, i + (up ? -1 : 1)); destinationItem->setBackgroundColor(QColor(150,0,0)); ui->workbenchTable->setItem(rowIndex, i, destinationItem); ui->workbenchTable->setItem(rowIndex, i + (up ? -1 : 1), sourceItem); }
But it's not working. I read somewhere that it doesnt work for widgets that have been created with setCellWidget.
So my questions are :
- Is QTableWidget the best option here ? I have thought about using QListWidget but I seem to recall that QListWidget can only show static widget. So you can have a button, but can't connect it.
- How to swap my rows if QTableWidget is the way to go?
Thanks!
-
I'm working on a QTableWidget :
I'm trying to make it possible to rearrange the rows with those 'up' 'down' buttons that I just added, or even better by drag and drop.
I have seen many post about this, and no obvious answers. It is weird it feels like an extremely basic task for a table yet I couldn't find a solution yet.
I tried the following :for (int i = 0; i < columnCount; i++) { QTableWidgetItem* sourceItem = ui->workbenchTable->takeItem(rowIndex, i); QTableWidgetItem* destinationItem = ui->workbenchTable->takeItem(rowIndex, i + (up ? -1 : 1)); destinationItem->setBackgroundColor(QColor(150,0,0)); ui->workbenchTable->setItem(rowIndex, i, destinationItem); ui->workbenchTable->setItem(rowIndex, i + (up ? -1 : 1), sourceItem); }
But it's not working. I read somewhere that it doesnt work for widgets that have been created with setCellWidget.
So my questions are :
- Is QTableWidget the best option here ? I have thought about using QListWidget but I seem to recall that QListWidget can only show static widget. So you can have a button, but can't connect it.
- How to swap my rows if QTableWidget is the way to go?
Thanks!
@Paddle For cellWidgets, you can try to swap them.
auto cell_widget = your_table->cellWidget(int row, int column); your_table->removeCellWidget(int row, int column); your_table->setCellWidget(int new_row, int new_column, cell_widget);
Note that cell widget is added on top of item. You can not swap items for cell widgets and they have to be swapped separately, I guess.
-
I'm working on a QTableWidget :
I'm trying to make it possible to rearrange the rows with those 'up' 'down' buttons that I just added, or even better by drag and drop.
I have seen many post about this, and no obvious answers. It is weird it feels like an extremely basic task for a table yet I couldn't find a solution yet.
I tried the following :for (int i = 0; i < columnCount; i++) { QTableWidgetItem* sourceItem = ui->workbenchTable->takeItem(rowIndex, i); QTableWidgetItem* destinationItem = ui->workbenchTable->takeItem(rowIndex, i + (up ? -1 : 1)); destinationItem->setBackgroundColor(QColor(150,0,0)); ui->workbenchTable->setItem(rowIndex, i, destinationItem); ui->workbenchTable->setItem(rowIndex, i + (up ? -1 : 1), sourceItem); }
But it's not working. I read somewhere that it doesnt work for widgets that have been created with setCellWidget.
So my questions are :
- Is QTableWidget the best option here ? I have thought about using QListWidget but I seem to recall that QListWidget can only show static widget. So you can have a button, but can't connect it.
- How to swap my rows if QTableWidget is the way to go?
Thanks!
@Paddle said in Swap rows QTableWidget:
I'm trying to make it possible to rearrange the rows
bool QAbstractItemModel::moveRow(const QModelIndex &sourceParent, int sourceRow, const QModelIndex &destinationParent, int destinationChild) allows a row to be moved in a model. Assuming the model used by
QTableWidget
implements this that should allow re-ordering. I don't know whether the fact there are cell widgets would be relevant. -
@Paddle For cellWidgets, you can try to swap them.
auto cell_widget = your_table->cellWidget(int row, int column); your_table->removeCellWidget(int row, int column); your_table->setCellWidget(int new_row, int new_column, cell_widget);
Note that cell widget is added on top of item. You can not swap items for cell widgets and they have to be swapped separately, I guess.
@JoeCFD said in Swap rows QTableWidget:
@Paddle For cellWidgets, you can try to swap them.
auto cell_widget = your_table->cellWidget(int row, int column); your_table->removeCellWidget(int row, int column); your_table->setCellWidget(int new_row, int new_column, cell_widget);
Note that cell widget is added on top of item. You can not swap items for cell widgets and they have to be swapped separately, I guess.
Thanks. This doesn't work. Apparantly from what I read, when you call removeCellWidget the widget is destroyed. It seems that ownership of the widget cannot be changed.
-
@JoeCFD said in Swap rows QTableWidget:
@Paddle For cellWidgets, you can try to swap them.
auto cell_widget = your_table->cellWidget(int row, int column); your_table->removeCellWidget(int row, int column); your_table->setCellWidget(int new_row, int new_column, cell_widget);
Note that cell widget is added on top of item. You can not swap items for cell widgets and they have to be swapped separately, I guess.
Thanks. This doesn't work. Apparantly from what I read, when you call removeCellWidget the widget is destroyed. It seems that ownership of the widget cannot be changed.
-
@Paddle said in Swap rows QTableWidget:
I'm trying to make it possible to rearrange the rows
bool QAbstractItemModel::moveRow(const QModelIndex &sourceParent, int sourceRow, const QModelIndex &destinationParent, int destinationChild) allows a row to be moved in a model. Assuming the model used by
QTableWidget
implements this that should allow re-ordering. I don't know whether the fact there are cell widgets would be relevant.@JonB said in Swap rows QTableWidget:
@Paddle said in Swap rows QTableWidget:
I'm trying to make it possible to rearrange the rows
bool QAbstractItemModel::moveRow(const QModelIndex &sourceParent, int sourceRow, const QModelIndex &destinationParent, int destinationChild) allows a row to be moved in a model. Assuming the model used by
QTableWidget
implements this that should allow re-ordering. I don't know whether the fact there are cell widgets would be relevant.I tried the following but nothing happens. Am I doing something wrong?
QModelIndex sourceParent = ui->workbenchTable->model()->index(rowIndex, 0); QModelIndex destinationParent = ui->workbenchTable->model()->index(rowIndex + (up ? -1 : 1), 0); ui->workbenchTable->model()->moveRow(sourceParent, rowIndex, destinationParent, rowIndex + (up ? -1 : 1));
-
@Paddle Sorry, I missed that one. Maybe you can create a new one and it does not cost anything, right?
-
@JoeCFD said in Swap rows QTableWidget:
@Paddle Sorry, I missed that one. Maybe you can create a new one and it does not cost anything, right?
No problem of course, your suggestions are very welcome.
I guess I can recreate the widget yes. I'll try that
-
@JonB said in Swap rows QTableWidget:
@Paddle said in Swap rows QTableWidget:
I'm trying to make it possible to rearrange the rows
bool QAbstractItemModel::moveRow(const QModelIndex &sourceParent, int sourceRow, const QModelIndex &destinationParent, int destinationChild) allows a row to be moved in a model. Assuming the model used by
QTableWidget
implements this that should allow re-ordering. I don't know whether the fact there are cell widgets would be relevant.I tried the following but nothing happens. Am I doing something wrong?
QModelIndex sourceParent = ui->workbenchTable->model()->index(rowIndex, 0); QModelIndex destinationParent = ui->workbenchTable->model()->index(rowIndex + (up ? -1 : 1), 0); ui->workbenchTable->model()->moveRow(sourceParent, rowIndex, destinationParent, rowIndex + (up ? -1 : 1));
@Paddle said in Swap rows QTableWidget:
I tried the following but nothing happens. Am I doing something wrong?
It returns a
bool
which you can check to see if it worked. Unfortunately I think your code looks correct, so does it return false?.QAbstractItemModel::moveRows()
does that and does nothing by default, the derived class has to implement it. IfQTableWidget
's model does not do that then this is a blind alley. -
@Paddle said in Swap rows QTableWidget:
I tried the following but nothing happens. Am I doing something wrong?
It returns a
bool
which you can check to see if it worked. Unfortunately I think your code looks correct, so does it return false?.QAbstractItemModel::moveRows()
does that and does nothing by default, the derived class has to implement it. IfQTableWidget
's model does not do that then this is a blind alley.In the end I got it working by creating new widgets and swapping their layout:
auto widget = ui->workbenchTable->cellWidget(rowIndex, 0); auto widget2 = ui->workbenchTable->cellWidget(rowIndex + (up ? -1 : 1), 0); auto newWidget = new QWidget(this); newWidget->setObjectName(widget->objectName()); newWidget->setLayout(widget->layout()); auto newWidget2 = new QWidget(this); newWidget2->setObjectName(widget2->objectName()); newWidget2->setLayout(widget2->layout()); ui->workbenchTable->removeCellWidget(rowIndex, 0); ui->workbenchTable->removeCellWidget(rowIndex + (up ? -1 : 1), 0); ui->workbenchTable->setCellWidget(rowIndex + (up ? -1 : 1), 0, newWidget); ui->workbenchTable->setCellWidget(rowIndex , 0, newWidget2);
-
In the end I got it working by creating new widgets and swapping their layout:
auto widget = ui->workbenchTable->cellWidget(rowIndex, 0); auto widget2 = ui->workbenchTable->cellWidget(rowIndex + (up ? -1 : 1), 0); auto newWidget = new QWidget(this); newWidget->setObjectName(widget->objectName()); newWidget->setLayout(widget->layout()); auto newWidget2 = new QWidget(this); newWidget2->setObjectName(widget2->objectName()); newWidget2->setLayout(widget2->layout()); ui->workbenchTable->removeCellWidget(rowIndex, 0); ui->workbenchTable->removeCellWidget(rowIndex + (up ? -1 : 1), 0); ui->workbenchTable->setCellWidget(rowIndex + (up ? -1 : 1), 0, newWidget); ui->workbenchTable->setCellWidget(rowIndex , 0, newWidget2);
Sub question: How do you enable drap and drop to move rows ?
I used
ui->workbenchTable->setDragDropMode(QAbstractItemView::InternalMove); ui->workbenchTable->setSelectionMode(QAbstractItemView::SingleSelection); ui->workbenchTable->setSelectionBehavior(QAbstractItemView::SelectRows); ui->workbenchTable->viewport()->setAcceptDrops(true); ui->workbenchTable->setDropIndicatorShown(true); ui->workbenchTable->setDragEnabled(true); ui->workbenchTable->setAcceptDrops(true); ui->workbenchTable->setDefaultDropAction(Qt::MoveAction); ui->workbenchTable->setDragDropOverwriteMode(false);
with this the rows can be dragged, meaning clicking them and dragging moves a rectangle around (the widget itself is not visible in the dragged rectangle).
But when I drop nothing happens.
How do I connect the signal or catch the drop event? Thanks
-
Sub question: How do you enable drap and drop to move rows ?
I used
ui->workbenchTable->setDragDropMode(QAbstractItemView::InternalMove); ui->workbenchTable->setSelectionMode(QAbstractItemView::SingleSelection); ui->workbenchTable->setSelectionBehavior(QAbstractItemView::SelectRows); ui->workbenchTable->viewport()->setAcceptDrops(true); ui->workbenchTable->setDropIndicatorShown(true); ui->workbenchTable->setDragEnabled(true); ui->workbenchTable->setAcceptDrops(true); ui->workbenchTable->setDefaultDropAction(Qt::MoveAction); ui->workbenchTable->setDragDropOverwriteMode(false);
with this the rows can be dragged, meaning clicking them and dragging moves a rectangle around (the widget itself is not visible in the dragged rectangle).
But when I drop nothing happens.
How do I connect the signal or catch the drop event? Thanks
Hi,
You should use InternalMove if you plan to only move things around within the same QTableWidget.
That said, you really should consider implementing delegates. As explained in the documentation, setCellWidget should only be used to show some static content.