3

Python の QAbstractItemModel でリストをラップして、PyQt に付属する GUI の利点を使用してリストをツリーとして表示できるようにしようとしています。正確には、PyQt5 と Python 3.3 を使用しています。

リスト項目へのポインターを明示的に生成しようとしましたが、親項目の識別に問題がありました。私はそれらを割り当てていません.createIndexを実行したときにPyQtがそれらをどのように割り当てるか、または割り当てるかどうかはわかりません. 次に、ネストされたリスト ["A",["a",[1,2,3]],"B", "C",["b",[4,5,6],"d"]] 次に、[4,1,1] を使用して 5 を指すことができます。次に、同じリストから最後の項目を除いたものを使用して親を取得します。 、[4,1]。

私の問題はこれです。行の値から生成されたリストを使用すると、CREATEINDEX メソッドによってコードがクラッシュします。私の、Minimum Broken Example (MBE) は以下のとおりです。"return self.createIndex(row,col,ptr)" を含む 2 行のコメントを外して、説明した内訳を確認します。

from PyQt5.QtGui     import QFont, QColor
from PyQt5.QtCore    import QAbstractItemModel, QModelIndex, Qt, QAbstractListModel, QAbstractTableModel, QSize, QVariant
from PyQt5.QtWidgets import QApplication, QTreeView, QTableView, QListView

class NodeTree(QAbstractItemModel) :
 def __init__(self,parent,data) :
  super(NodeTree,self).__init__(parent)
  self.data   = data

 def rowCount(self, parent = QModelIndex()) :
  # int rowCount (self, QModelIndex parent = QModelIndex())
  if parent.isValid() :
   data = self.data
   for idx in parent.internalPointer() :
    data = data[idx]
   return len(data)
  else : 
   return len(self.data)  

 def columnCount(self, parent = QModelIndex()) :
  # int columnCount (self, QModelIndex parent = QModelIndex())
  return 1

 def data(self, index = QModelIndex(), role = None) :  
  # QVariant data (self, QModelIndex index, int role = Qt.DisplayRole)
  if role == 0 :
   if index.isValid() :
    return str(index.internalPointer())
   else : 
    return "No Data" 
  return None

 def index(self,row,col, parent = QModelIndex()):
  # QModelIndex index (self, int row, int column, QModelIndex parent = QModelIndex())
  # QModelIndex createIndex (self, int arow, int acolumn, int aid)
  # QModelIndex createIndex (self, int arow, int acolumn, object adata = 0)
  if parent.isValid() :
   ptr = [parent.internalPointer(),row]
#     return self.createIndex(row,col,ptr)
   return QModelIndex()
  else :
   ptr = [row]
#    return self.createIndex(row,col,ptr)
   return QModelIndex()
  return QModelIndex() 

 def parent(self, child = QModelIndex()): 
  # QObject parent (self)
  if child.isValid() :
   print(child.internalPointer())
  return QModelIndex()

if __name__ == "__main__" :
 # http://blog.mathieu-leplatre.info/filesystem-watch-with-pyqt4.html
 import sys

 app = QApplication(sys.argv)
 TreeView  = QTreeView()
 TreeModel = NodeTree(TreeView, [['A',['a',1]],['C','D'],['E','F']])
 TreeView.setModel(TreeModel)
 TreeView.show()
 app.exec_()

私が理解していないのは、QModelIndex が CREATEINDEX 内で作成される方法と、INDEX メソッド内でオンザフライで生成されたリストでクラッシュする理由です。私にとって、INTERNALPOINTERは呼び出し間で保持されるべきであり、リストを渡すことは問題ないはずです。

私を混乱させるもう 1 つのことは、いつ、なぜ親とインデックスが呼び出されるかということです。私が理解しているように、インデックスはツリーを下にトラバースし、親は上にトラバースします。したがって、INDEX の呼び出しは (row,col) で親の子を識別し、PARENT は子を識別し、親を決定します。内部ポインタへの参照は完了していますか? もしそうなら、なぜ QmodelIndex は独自の PARENT メソッドを維持するのでしょうか。Qtは、インデックスと親の間の呼び出しに基づいてアイテム間の階層を確立する独自の内部ツリーを維持しているようです。つまり、My モデル用と表示用の 2 つのツリーが常に存在します。

4

2 に答える 2

7

あなたの援助はこの入力リストから得られると思います

[['A',['a',1]],['C','D'],['E','F']]

次の出力

ここに画像の説明を入力

あなたのコードは主にこれらの点で失敗します(私の意見では):

  • ツリー モデルとツリー アイテム データを分割しないため、混乱が生じます。
  • 最初のポイントに関連して、Qt ModelIndex だけでなく、データに基づいていくつかのプロパティを計算します。

次のコードでは、TreeView コンポーネントのqt サンプル コード(C++)との 1 対 1 の関係を可能な限り近づけようとしています (ここのように) 。

from PyQt5.QtCore    import (
   QAbstractItemModel, 
   QModelIndex, 
   Qt, 
   QVariant
)

from PyQt5.QtWidgets import QApplication, QTreeView

class TreeItem(object):
    def __init__(self, content, parentItem):
        self.content = content
        self.parentItem = parentItem
        self.childItems = []

    def appendChild(self, item):
        self.childItems.append(item)

    def child(self, row):
        return self.childItems[row]

    def childCount(self):
        return len(self.childItems)

    def columnCount(self):
        return 1

    def data(self, column):
        if self.content != None and column == 0:
           return QVariant(self.content)

        return QVariant()

    def parent(self):
        return self.parentItem

    def row(self):
        if self.parentItem:
            return self.parentItem.childItems.index(self)
        return 0

class NodeTree(QAbstractItemModel):
   def __init__(self,parent,data) :
      super(NodeTree,self).__init__(parent)
      self.rootItem = TreeItem(None, None)
      self.parents = {0 : self.rootItem}
      self.setupModelData(self.rootItem, data)

   def setupModelData(self, root, data):
      for el in data:
         if isinstance(el, list):
            item = TreeItem("Node", root)
            self.setupModelData(item, el)
         else:
            item = TreeItem(el, root)
         root.appendChild(item)

   def rowCount(self, parent = QModelIndex()):
      if parent.column() > 0:
         return 0
      if not parent.isValid():
         p_Item = self.rootItem
      else:
         p_Item = parent.internalPointer()
      return p_Item.childCount() 

   def columnCount(self, parent = QModelIndex()):
      return 1

   def data(self, index, role):
       if not index.isValid():
           return QVariant()

       item = index.internalPointer()
       if role == Qt.DisplayRole:
           return item.data(index.column())
       if role == Qt.UserRole:
           if item:
               return item.content

       return QVariant()

   def headerData(self, column, orientation, role):
       if (orientation == Qt.Horizontal and
                role == Qt.DisplayRole):
           return QVariant("Content")

       return QVariant()

   def index(self, row, column, parent):
       if not self.hasIndex(row, column, parent):
          return QModelIndex()

       if not parent.isValid():
          parentItem = self.rootItem
       else:
          parentItem = parent.internalPointer()

       childItem = parentItem.child(row)
       if childItem:
          return self.createIndex(row, column, childItem)
       else:
          return QModelIndex()

   def parent(self, index):
       if not index.isValid():
          return QModelIndex()

       childItem = index.internalPointer()
       if not childItem:
          return QModelIndex()

       parentItem = childItem.parent()

       if parentItem == self.rootItem:
          return QModelIndex()

       return self.createIndex(parentItem.row(), 0, parentItem)

if __name__ == "__main__" :
   # http://blog.mathieu-leplatre.info/filesystem-watch-with-pyqt4.html
   import sys

   app = QApplication(sys.argv)
   TreeView  = QTreeView()
   TreeModel = NodeTree(TreeView, [['A',['a',1]],['C','D'],['E','F']])
   TreeView.setModel(TreeModel)
   TreeView.show()
   app.exec_()

これがお役に立てば幸いです。

于 2014-04-18T20:11:49.217 に答える