Ich versuche, Drag & Drop zu arbeiten zwischen zwei QListViews mit einem benutzerdefinierten QStandardItem. Ich kann nicht die Informationen finden, die ich online außer this document brauche, die ein wenig half, aber jetzt bin ich fest.So löschen Sie ein benutzerdefiniertes QStandardItem in eine QListView
Drag & Drop von einem QListView auf ein anderes funktioniert gut, wenn ich einen QStandardItem verwenden, um meine Daten zu halten, aber wenn ich einen benutzerdefinierten Artikel verwende ich laufen in Schwierigkeiten, weil die Empfangs Model/View eine QStandardItem erzeugt, wenn eine benutzerdefinierte Artikel ist fallen gelassen.
Im Idealfall könnte ich dem empfangenden Modell sagen, dass ich mein benutzerdefiniertes Objekt als Standard-Objekt verwenden soll, und ansonsten tue es einfach, aber ich nehme an, es wird nicht so einfach sein ?! Es scheint, dass alles funktioniert out of the box außer der Schaffung der QStandardItem nach dem Drop, anstatt meine benutzerdefinierte Artikel, so hoffe ich, ich muss nicht neu erfinden (Drag & Drop) Rad, nur um diese zu bekommen Teil rechts ?!
Wenn ich das Rad neu erfinden und die Ansicht dropEvent der Ansicht implementieren muss, um die eingehenden Artikel dann manuell anzufügen, stoße ich auf eine andere Kuriosität. Hier ist mein Test-Code (einschließlich einige Code zum Dekodieren der abgelegten Daten, die ich online gefunden):
from PySide import QtCore, QtGui
class MyItem(QtGui.QStandardItem):
'''This is the item I'd like to drop into the view'''
def __init__(self, parent=None):
super(MyItem, self).__init__(parent)
self.testAttr = 'test attribute value'
class ReceivingView(QtGui.QListView):
'''Custom view to show the problem - i.e. the dropEvent produces a QStandardItem rather than MyItem'''
def __init__(self, parent=None):
super(ReceivingView, self).__init__(parent)
def decode_data(self, bytearray):
'''Decode byte array to receive item back'''
data = []
item = {}
ds = QtCore.QDataStream(bytearray)
while not ds.atEnd():
row = ds.readInt32()
column = ds.readInt32()
map_items = ds.readInt32()
for i in range(map_items):
key = ds.readInt32()
value = MyItem()
ds >> value
#item[QtCore.Qt.ItemDataRole(key)] = value
item = value
data.append(item)
return data
def dropEvent(self, event):
byteArray = event.mimeData().data('application/x-qabstractitemmodeldatalist')
for item in self.decode_data(byteArray):
copiedItem = MyItem(item)
newItem = MyItem('hello')
print copiedItem
print newItem
self.model().appendRow(copiedItem) # the copied item does not show up, even though it is appended to the model
#self.model().appendRow(newItem) # this works as expected
event.accept()
item = self.model().item(self.model().rowCount() - 1)
print item
if __name__ == "__main__":
import sys
app = QtGui.QApplication(sys.argv)
mw = QtGui.QMainWindow()
w = QtGui.QSplitter()
mw.setCentralWidget(w)
# models
model1 = QtGui.QStandardItemModel()
model2 = QtGui.QStandardItemModel()
for i in xrange(5):
#item = QtGui.QStandardItem()
item = MyItem()
item.setData(str(i), QtCore.Qt.DisplayRole)
model1.appendRow(item)
# views
view1 = QtGui.QListView()
view2 = ReceivingView()
for v in (view1, view2):
v.setViewMode(QtGui.QListView.IconMode)
view1.setModel(model1)
view2.setModel(model2)
w.addWidget(view1)
w.addWidget(view2)
mw.show()
mw.raise_()
sys.exit(app.exec_())
Die Idee ist, die abgelegten Daten zu dekodieren das ursprüngliche Einzelteil zurück zu erhalten, dann eine Kopie erstellen und diese Kopie anhängen zum empfangenden Modell. Das benutzerdefinierte Objekt wird an das Modell angehängt, wird jedoch nach dem Ereignis drop nicht in der Ansicht angezeigt. Wenn ich ein neues benutzerdefiniertes Element innerhalb des Drop-Even-Objekts erstelle und dieses anhefte, funktioniert alles wie erwartet.
Also habe ich zwei Fragen in Bezug auf die oben:
- Ist dieser Ansatz des richtigen den Abwurf von benutzerdefinierten Elementen oder ist es ein einfacher ein aktivieren?
- Warum wird die Kopie des benutzerdefinierten Elements im obigen Code nach dem Löschen nicht in der Ansicht angezeigt?
Vielen Dank im Voraus, frank
fragte ich [diese Frage] (http://stackoverflow.com/questions/41991840/pyside-qlistview-creating-new-item -during-Drag-and-Drop-eher-als-Passing-oder) ein wenig früher. Ich habe versucht, Ihrer Lösung zu folgen, aber ich kann immer noch keine benutzerdefinierten Daten über ein Bewegungsereignis verwalten. Ich bin nicht sicher, wie man die 'setData' Methode richtig implementiert. Könntest du ein bisschen darüber hinausgehen, wie man "setData" richtig implementiert? Ich bin mir nicht sicher, was das beste Format für diese Diskussion ist (neue Frage?), Aber hier ist [mein Code mit Änderungen] (https://www.pastiebin.com/5892bb18723f8). – Johndt6
@ Johndt6. Ich fügte ein Beispiel von dem hinzu, was ich zu meiner Antwort meinte. Die Idee ist, die Verwendung dynamischer Python-Attribute vollständig zu vermeiden. Die Verwendung von "@ Eigenschaft" ist nur syntaktischer Zucker. Eine viel einfachere Implementierung wäre es, bei den reinen Qt-APIs zu bleiben: dh die 'QStandardItem'-Komfortmethoden wie 'text()'/'setText()', plus 'data()'/'setData()' für beliebige benutzerdefinierte Werte . Es sollte nicht nötig sein, etwas anderes als "clone()" neu zu implementieren. Die einzigen Dinge, die relevant sind, sind die Artikelflags und Daten. – ekhumoro