PySide:QAbstractItemModel不与简单的控件

时间:2016-02-22 19:24:25

标签: pyqt pyqt4 pyside

使用PySide,我试图将几个数据控件连接到我从光盘读取的文件中的数据。所以我创建了一个从QAbstractItemModel派生的数据模型。应该是微不足道的吧?但是我遇到的一个问题是连接QLineEdit和QTextEdit控件来显示和允许编辑模型中的数据。

从QT文档中的Simple Widget Mapper和Combo Widget Mapper等示例中,我相信我必须拥有一行数据模型,并使用QWidgetMapper将该行中的单元格连接到编辑控件。 / p>

这是一个非常简化的程序,可以显示问题。此示例中的数据模型返回三个字符串x1,x2和x3。字符串从例如通过调用Update来“First(1)”到“First(2)”,即单击“Next”按钮。这是为了模拟从文件或任何地方读取的新值。主窗口有几个QLineEdits和一个QTextEdit,映射器应链接到模型数据。但数据不会显示在编辑控件中。

为了检查模型,我添加了一个QTableView。数据显示在那里,并在单击“下一步”时更新,因此它不是数据模型。这是在那里和编辑控件之间的东西。但我看不到我在做什么,小部件映射器示例正在做什么。

我做错了什么?

顺便说一下,走另一条路也行不通。如果我将一个setData()方法添加到模型中,并发出dataChanged,则键入行编辑的更改将转到表中。但即使发生这种情况,该项目也会从行编辑中消失。单击“下一步”后,将停止为QLineEdit和QTextEdit工作 - 不再调用setData()。但是如果我在表视图中编辑,仍会调用setData。

以下是示例代码:

#!/usr/bin/python

import sys
from PySide.QtCore import ( Qt, QAbstractItemModel,QModelIndex
                          )
from PySide.QtGui import ( QApplication, QMainWindow, QPushButton, QWidget,
                           QTextEdit, QLineEdit, QFormLayout, QTableView,
                           QDataWidgetMapper, 
                         )

##############################################################################
class TModel(QAbstractItemModel):
  """
  This model will have 1 row of 3 items

  There will be a slot that will change the items. If they are displayed
  in widgets, I want to see them update.
  """

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

    self.counter = 0
    self.x1 = ""
    self.x2 = ""
    self.x3 = ""
    self.Update()

  def columnCount(self, index=QModelIndex()):
    return 3

  def rowCount(self, index=QModelIndex()):
    return 1

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

  def parent(self, index):
    return QModelIndex()

  def hasChildren(self, index):
    return False

  def data(self, index, role=Qt.DisplayRole):
    if index.isValid():
      if role == Qt.DisplayRole:
        if index.column() == 0:
          return self.x1
        elif index.column() == 1:
          return self.x2
        elif index.column() == 2:
          return self.x3

    return None

  def headerData(self, section, orientation, role):
    if role != Qt.DisplayRole:
      return None

    if orientation == Qt.Horizontal:
      if section == 0:
        return "col 1"
      elif section == 1:
        return "col 2"
      elif section == 2:
        return "col 3"

  def Update(self):
    self.beginResetModel()
    self.x1 = "First (%d)"%self.counter
    self.x2 = "Second (%d)"%self.counter
    self.x3 = "Third (%d)"%self.counter
    self.counter += 1
    self.endResetModel()



##############################################################################
class TMainWindow(QMainWindow):
  """Main GUI object"""

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

    self.DataModel = TModel()

    self.Mapper = QDataWidgetMapper()
    self.Mapper.setSubmitPolicy(self.Mapper.AutoSubmit)
    self.Mapper.setModel(self.DataModel)

    self.FirstFieldEdit = QLineEdit()
    self.SecondFieldEdit = QLineEdit()
    self.ThirdFieldEdit = QTextEdit()

    self.Mapper.addMapping(self.FirstFieldEdit, 0)
    self.Mapper.addMapping(self.SecondFieldEdit, 1)
    self.Mapper.addMapping(self.ThirdFieldEdit, 2)
    self.Mapper.toFirst()

    self.UpdateButton = QPushButton("Next")
    self.UpdateButton.clicked.connect(self.DataModel.Update)

    formLayout = QFormLayout()
    formLayout.addRow("&First:",  self.FirstFieldEdit)
    formLayout.addRow("&Second:", self.SecondFieldEdit)
    formLayout.addRow("&Third:",  self.ThirdFieldEdit)
    formLayout.addRow("",         self.UpdateButton)

    self.testTable = QTableView()
    self.testTable.setModel(self.DataModel)
    formLayout.addRow("Table:", self.testTable)

    W = QWidget()
    W.setLayout(formLayout)
    self.setCentralWidget(W)



##############################################################################

if __name__ == "__main__":
  app = QApplication(sys.argv)
  MainWindow = TMainWindow()
  MainWindow.show()
  sys.exit(app.exec_())

1 个答案:

答案 0 :(得分:1)

QDataWidgetMapper类旨在允许在模型中显示和编辑记录。但是,当请求编辑数据时,您的模型不会返回任何内容。所以一个简单的解决方案是:

    def data(self, index, role=Qt.DisplayRole):
        if index.isValid():
            if role == Qt.DisplayRole or role == Qt.EditRole:
                ...

修改

来自Qt Docs:

  

QDataWidgetMapper可用于通过映射创建数据感知小部件   它们是项目模型的部分。如果是,则部分是模型的   方向是水平的(默认),否则是。 [强调补充]

我建议你避免尝试编写一个自定义模型(除了最简单的情况,这是非常微不足道的),然后使用QStandardItemModel开始。