Moving a cell widget in a QTableWidget?
-
I'm trying to write a general class derived from
QTableWidget
that allows dragging and dropping any of its rows to reorder them when it's set to only allow selecting rows. This is based on the implementation in this (still unresolved) feature request here: https://bugreports.qt.io/browse/QTBUG-13873I've hit a snag, though: some of the table widgets I want to use with my subclass have cell widgets, set using
QTableWidget::setCellWidget
.QTableWidget
provides methods for setting and removing cell widgets, but not moving them.Looking at the source code for
setCellWidget
, I see that it calls intoQAbstractItemView::setIndexWidget
, which when removing a widget always callsdeleteLater
on it. So getting a reference to an existing widget, removing it as a cell widget, and then re-adding it as a cell widget to a different cell will not work. There is also no way to clone an arbitraryQWidget
that I'm aware of, so that means I can't copy the widget and then add the copy as a cell widget.It looks like I'm SOL. I'm hoping though that there's some way I can actually have a
QTableWidget
move its cell widgets around. Does anyone have any ideas?(If not, then this is a use case that ought to be supported by
QTableWidget
!) -
@SGaist said in Moving a cell widget in a QTableWidget?:
Well, the stated goal of setCellWidget is to show static content hence moving them around is not really part of the static content concept.
That's too bad, and it seems like it's missing an obvious use case. I'm using cell widgets to display data in the table that is better served by a specific widget rather than just text in a cell. But since it's displaying data, it ought to be able to be moved around by dragging and dropping like every other cell, especially when it selects by row.
In any case, I did find a solution! It's quite the hack and I really, really wish there was a better way to do it, but it works.
After the user drops a row on to my table widget, I create a new column, populate it with integers that correspond to the new row indices after the drop, sort the table widget using that column, and then remove the column.
I came upon this solution when I discovered that sorting the table widget would also move the cell widgets. It seems the trick is that it's calling
changePersistentIndexList()
behind the scenes, but even when subclassing there's no way for me to get access to the underlying model of the table and call that function to reorder things myself.It'd be great if:
- QTableWidget had built-in support for dragging and dropping rows when it's set to select by row
- Failing the above, there was a function for moving a cell widget to another cell so that you can implement the drag-and-drop behavior yourself.
-
Hi,
One possible way it could be implemented is to make the widget itself "dragable" and have the view handle the move and drop of it. By dragable I mean that you create a QDrag object from within the widget as part of its mouse handling.
-
@SGaist said in Moving a cell widget in a QTableWidget?:
Hi,
One possible way it could be implemented is to make the widget itself "dragable" and have the view handle the move and drop of it. By dragable I mean that you create a QDrag object from within the widget as part of its mouse handling.
You may misunderstand what I'm trying to do. The issue isn't that I can't drag and drop the widget cell if the drag starts on the widget. The issue is that there's no clear way to actually move the widget to another cell on a different row. This applies when dragging from anywhere in the row, not just on the widget itself.
Normally the way you'd move a row with a QTableWidget is to insert a new row, copy all of the QTableWidgetItem entries for each cell on the old row to the new row, and then remove the old row. This works because it's possible to duplicate a QTableWidgetItem. It's not possible to duplicate a QWidget, though, and the only options for setting a cell's widget is to either add a widget (which hands ownership of it to the table) or to remove the widget (which deletes it from memory). There's no method for moving it.
-
Well, the stated goal of setCellWidget is to show static content hence moving them around is not really part of the static content concept.
So indeed, the only solution is to use a widget that has a clone function that will copy whatever properties it has to a new instance and set that new instance to the cell you want before removing the old one.
-
@SGaist said in Moving a cell widget in a QTableWidget?:
Well, the stated goal of setCellWidget is to show static content hence moving them around is not really part of the static content concept.
That's too bad, and it seems like it's missing an obvious use case. I'm using cell widgets to display data in the table that is better served by a specific widget rather than just text in a cell. But since it's displaying data, it ought to be able to be moved around by dragging and dropping like every other cell, especially when it selects by row.
In any case, I did find a solution! It's quite the hack and I really, really wish there was a better way to do it, but it works.
After the user drops a row on to my table widget, I create a new column, populate it with integers that correspond to the new row indices after the drop, sort the table widget using that column, and then remove the column.
I came upon this solution when I discovered that sorting the table widget would also move the cell widgets. It seems the trick is that it's calling
changePersistentIndexList()
behind the scenes, but even when subclassing there's no way for me to get access to the underlying model of the table and call that function to reorder things myself.It'd be great if:
- QTableWidget had built-in support for dragging and dropping rows when it's set to select by row
- Failing the above, there was a function for moving a cell widget to another cell so that you can implement the drag-and-drop behavior yourself.
-
G Guy Gizmo has marked this topic as solved on