2017-08-23 135 views
0

我在嘗試在PyQt中學習模型/視圖時遇到了困難(請參閱此主題:Unable to inherit from QAbstractItemModel)。當我嘗試添加映射分配時,我的應用程序正在掛起。這裏是我的自定義數據模型類:QDataWidgetMapper.addMapping(...)導致應用程序掛起

class MyCustomDataModel(QAbstractItemModel): 

    def __init(self, parent = None): 
     super(MyCustomDataModel, self).__init__(parent) 

     self.parent = None 


    def rowCount(self, parent): 
     return 1 

    def data(self, index, role): 

     if not index.isValid(): 
      return None 

     if role == Qt.DisplayRole or role == Qt.EditRole: 

      if index.column() == 0: 
       return self.parent.value0 
      elif index.column() == 1: 
       return self.parent.value1 
      elif index.column() == 1: 
       return self.parent.value2 

    def setData(self, index, value, role = Qt.EditRole): 

     if role == Qt.EditRole: 
      if index.column() == 0: 
       self.parent.value0 = value 
      elif index.column() == 1: 
       self.parent.value1 = value 
      elif index.column() == 2: 
       self.parent.value2 = value 

      self.dataChanged.emit(index, index) 

下面是嘗試使用數據模型的類。它包含了我想要映射到小部件變量:

class MyCustomType(AnotherCustomTypeThatInheritsQListWidgetItem): 

def __init__(self, parent = None): 
    super(MyCustomType, self).__init__(parent) 

    # Some member data: 
    self.value0 = 0 
    self.value1 = 1 
    self.value2 = 2 

    # Instantiate a model: 
    self.dataModel = MyCustomDataModel() 
    self.dataModel.parent = self 

我有一個包含三個QLineEdit的小部件的複合控件:

class MyCompositeWidget(QWidget): 

    def __init__(self, parent = None): 
     super(MyCompositeWidget, self).__init__(parent) 

     self.dataMapper = QDataWidgetMapper() 

     # Instantiate three line edits: 
     self.lineEdit1 = QLineEdit() 
     self.lineEdit2 = QLineEdit() 
     self.lineEdit3 = QLineEdit() 

     # Add widgets to layout, set layout, etc. Not shown but widgets display properly. 

    def Activate(self, anInstanceofMyCustomType): 

     self.dataMapper.setModel(anInstanceOfMyCustomType.dataModel) 
     self.dataMapper.addMapping(self.lineEdit1, 0) # This line causes application to hang indefinately 
     self.dataMapper.addMapping(self.lineEdit2, 1) 
     self.dataMapper.addMapping(self.lineEdit3, 2) 

在運行時,應用程序掛起在指定的「addMapping」呼在「激活(...)」功能中。我發現網上的教程很不明確,並且在這裏遇到了障礙。我不得不承認我對「index.column()」映射很困惑,但我相信這是如何將索引分配給數據成員。無論如何,任何幫助都非常感謝......我花了很多時間試圖學習這一點,到目前爲止沒有任何真正的展示。

+0

去這裏的一種方法是刪除所有不必要的東西,然後進一步簡化代碼,直到達到可行的狀態。一個最小但完整的例子會幫助其他人調查問題。 – Trilarion

回答

1

我不確定您對Qt的Model-View編程框架的類有很好的理解。我推薦閱讀its documentation(你可以跳過關於拖放和proxys的部分)。如果有必要,請多閱讀一遍,但我花了一段時間才完全理解它。

無論如何,重要的一點是有幾個場景,並且您在這些場景中使用不同的類。從簡單到複雜,它們是:

  1. 使用便利等級。當你有一個小模型時,你可以使用它,並且你只有一個小部件,你可以通過它查看模型的 。在這種情況下,您使用convinience classes, ,它們的名稱均以'Widget'結尾:QListWidget,QTableWidget, 和QTreeWidget。他們沒有鏈接到一個單獨的模型類,你直接填寫它們的相應項目類別:QListWidgetItem, QTableWidgetItem,和QTreeWidgetItem。所有這些類都不是被分類的!正如您現在所經歷的,覆蓋它們可能會導致未定義的行爲。
  2. 使用標準模型類。當你有小模型但想要在同一模型上有多個視圖時,可以使用它們。在這種情況下,您將創建一個QStandardItemModel並使用QStandardItem對象填充該對象。然後創建一個或多個視圖類(QListView,QTableViewQTreeView)並將它們連接到模型。
  3. 創建新模型。如果您有大型模型,這是最好的解決方案。您覆蓋其中一個基類,QAbstractListModel', 'QAbstactTableModel', or 'QAbstractItemModel(不幸的是,沒有QAbstractTreeModel),並實現各種方法。您應該覆蓋哪些方法取決於您希望模型具備的功能(請參閱Model Subclassing Reference)。這種方法的好處是更高的性能和靈活性。您的模型實現可以使用常規的Python數據結構,並且data方法將根據視圖請求僅返回可見單元格的數據。您可以使用常規的Python數據結構來存儲數據,不需要事先將數據放入Qt項目對象中。

不要混合上面的類。也就是說,不要將小部件項目放在標準模型中,反之亦然。

不知道更多關於您的情況,我認爲情況2適用於您最好的。因此,我建議您製作一個QStandardModel並填寫QStandardItem對象。在你的第一次迭代中,我將使用QListViewQTableView來檢查你的模型。只有當這個工作正常,我將它連接到DataWidgetMapper。開始簡單!

最後,請在下次做出正確的MVCE。確保它完成!例如,不要使用像anInstanceOfMyCustomType這樣的結構,而是向我們展示創建對象實例的實際代碼。否則,您可能會忽略關鍵信息。此外,它還允許我們自己重現問題,調查是否需要並檢查可能的答案。

相關問題