Solved QTableView mit QAbstractTableModel und Drag&Drop
-
Hallo,
Ich bin etwas überfordert wie ich mit
QTableView
undQAbstractTableModel
ein korrektes Drag&Drop einer ganzen Zeile implementieren soll. Ein unvollständiges Exemplar ist als YouTube Video im Abspann zu sehen.Leider hat es in den Examples kein 1:1 Beispiel dazu. Ein einfaches Beispiel mit
QTableView
undQAbstractTableModel
ist das "Address Book Example", aber ohne Drag&Drop. Das "Drag and Drop Puzzle Example" ist schon ganz anders und mit anderen Super-Klassen (QListWidget, QWidget
).
Auch in den Büchern [1][2], die ich gerade lese, finde ich nichts, das GENAU so ein Beispiel hat, obwohl es ein ganz einfaches Beispiel wäre...Ich habe auf Sender und auf Empfänger-Seite je eine Instanz der gleichen Klasse
TableModel
, die eine ListQList<MeasurementData>
beinhaltet.Ich schalte beim Sender
QTableView
sowie imQAbstractTableModel
alle Drag-Funktionen ein, auf View-Ebene wie auch auf Zell-Ebene im Model. Ich kann eine Zelle draggen und auch beim Empfänger droppen. In derdropMimeData()
Methode füge ich die serialisierten Daten wieder in dieQList<MeasurementData>
. Komisch finde ich aber, dass danach auf der Sender-Seite diesetData()
-Methode aufgerufen wird. Da die Zeile beim Sender nicht gelöscht wird, lösche ich sie in dersetData()
-Methode. In der darauffolgenden "data()"-Methode möchte nun die View plötzlich die Zeile anzeigen, die ich zuvor gelöscht habe (Debug Meldung"Should not happen!!"
).- Wie implementiere ich Drag&Drop richtig, damit Model und View beide zufrieden sind?
- Im Video-Exemplar auf YouTube kann ich zwar Zeilen verschieben, wenn ich sie unter die vorhandenen Zeilen droppe. Wie kann ich auch Zeilen verschieben, wenn ich sie auf bestehende Zeilen droppe? Ziel: neue Zeile erstellen, nicht ersetzen.
- Nur Kosmetisch: statt auf eine Zelle zu droppen wäre es schön zwischen zwei bestehenden Zeilen ein "Indikator" darzustellen. Ist das mit wenig Aufwand möglich?
GitHub Projekt: DragAndDrop
YouTube Video: QTableView ProblemTutorials auf
doc.qt.io
Model/View Tutorial
Model/View Programming[1] The Book of Qt 4, Daniel Molkentin
[2] Advanced Qt Programming, Mark Summerfield -
-
Ich konnte das Drag&Drop selber lösen. Zum einen hätte ich gewisse Signale gar nicht "emittieren" sollen. Zum anderen hätte ich statt im
dropMimeData()
die Daten direkt in die ListeQList<MeasurementData>
zuerst mitinsertRows()
eine Zeile hinzufügen und danach jede Zelle einzeln mitsetData()
abfüllen sollen. -
Nachdem
dropMimeData()
seinen Teil gemacht hat, habe ich das manuelle Löschen imsetData()
entfernt (im Code auskommentiert). Stattdessen habe ich aufQTableView::setDragDropOverwriteMode(false)
gesetzt, was standartmässig auftrue
ist. Dann löscht dieQTableView
internt auf der Sender-Seite die Zeile mitQTableView::removeRows()
. -
Da habe ich noch keine Lösung gefunden. Ich vermute etwas mit
QTableView::setItemDelegate()
wäre möglich...
Code ist upgedatet auf github.com/te-bachi/QtProjects/DragAndDrop/
-