2017-08-23 178 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这样的结构,而是向我们展示创建对象实例的实际代码。否则,您可能会忽略关键信息。此外,它还允许我们自己重现问题,调查是否需要并检查可能的答案。

相关问题