2016-09-20 5 views
3

&のドロップを、カスタムQStandardItemを使用して2つのQListViewsの間で動作させようとしています。 少しでも助けたthis document以外のオンライン情報が見つかりませんでしたが、今は止まっています。カスタムQStandardItemをQListViewにドロップする方法

罰金別の作品に1 QListViewからドラッグ&ドロップに私は私のデータを保持するためにQStandardItemを使用しますが、私はトラブルに実行するカスタムアイテムを使用して、カスタムアイテムがあるときに受信モデル/ビューがQStandardItemを作成するため、落ちた

理想的には、自分のカスタムアイテムをデフォルトアイテムとして使用するように指示することができます。それ以外の場合はそれだけですが、それは簡単ではないと思いますか? 私のカスタムアイテムではなく、ドロップ時にQStandardItemの作成を除いてすべてが動作しているようですので、(&ドロップ)ホイールを再作成する必要はありません右の部分?

ホイールを再作成して、ビューのdropEventを実装して、着信アイテムを手動で追加する必要がある場合、私は別の奇妙なことに遭遇しています。ここでは(私はオンラインで見つけるドロップされたデータを復号化するためのいくつかのコードを含む)私のテストコードは次のとおりです。

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_()) 

アイデアがコピーを作成し、そのコピーを追加した後、元のアイテムを受け取るためにドロップされたデータを復号化するためにあります受信モデルに送信する。 カスタムアイテムはモデルに追加されますが、ドロップイベントの後のビューには表示されません。ドロップ内に新しいカスタムアイテムを作成して追加すると、すべてが期待通りに機能します。

  1. このアプローチは、カスタムアイテムのドロップを可能にするために正しいものですか簡単に1がある:

    は、だから私は、上記に関する二つの質問を得ましたか。
  2. 上記のコードのカスタムアイテムのコピーがドロップ後にビューに表示されないのはなぜですか?事前に

おかげで、 率直

答えて

3

あなたがsetItemPrototypeをしたいように見えます。これにより、モデルのアイテムファクトリが提供されるため、必要に応じていつでもカスタムクラスが暗黙的に使用されます。

あなたがする必要があるすべてはあなたの項目クラスでclone()を再実装されています

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' 

    def clone(self): 
     return MyItem() 

アンは、受信側の機種プロトタイプとして、そのクラスのインスタンスを設定します。

# models 
    model1 = QtGui.QStandardItemModel() 
    model2 = QtGui.QStandardItemModel() 
    model2.setItemPrototype(MyItem()) 

をあなたが忘れることができますすべてのデータストリームに関するもの。

PS:私はQtは、明らかに、アイテムの有効期間中に設定されている可能性があり、そしてアイテムが中に転送されたときに、それらがシリアライズされ得ることはありません任意のPythonのデータ属性について何も知らないことを指摘すべきであると仮定し

ドラッグアンドドロップ操作私は尋ねた

class MyItem(QtGui.QStandardItem): 
    _TestAttrRole = QtCore.Qt.UserRole + 2 

    def clone(self): 
     item = MyItem() 
     item.testArr = 'test attribute value' 
     return item 

    @property 
    def testAttr(self): 
     return self.data(self._TestAttrRole) 

    @testAttr.setter 
    def testAttr(self, value): 
     self.setData(value, self._TestAttrRole) 
+0

[この質問](http://stackoverflow.com/questions/41991840/pyside-qlistview-creating-new-item:あなたがそのようなデータを保持したい場合は、カスタムの役割をsetData()を使用ドラッグ&ドロップ、むしろちょっと早く過ぎるか、少し早く)私はあなたのソリューションに従うことを試みましたが、私はまだ移動イベントの間にカスタムデータを維持することができません。 'setData'メソッドを正しく実装する方法がわかりません。 'setData'を正しく実装する方法を少し拡張できますか?私はこのディスカッションを行う最良のフォーマットが何であるか(新しい質問?)がわかりませんが、ここには[変更された私のコード](https://www.pastiebin.com/5892bb18723f8)があります。 – Johndt6

+0

@ Johndt6。私は私の答えに何を意味するのかの例を加えました。このアイデアは、動的なpython属性の使用を完全に避けることです。 '@ property'の使用は構文的な砂糖だけです。はるかに簡単な実装は、純粋なQt API、すなわち 'text()'/'setText()'や任意のカスタム値の 'data()'/'setData()'のような 'QStandardItem'の便利なメソッドを使うことです。 。 'clone()'以外のものを再実装する必要はありません。関連する唯一のものはアイテムフラグとデータです。 – ekhumoro

関連する問題