TableView重新实现QAbstractTableModel后表中没有数据显示
Posted
技术标签:
【中文标题】TableView重新实现QAbstractTableModel后表中没有数据显示【英文标题】:TableView no data display in table after reimplementing QAbstractTableModel 【发布时间】:2019-10-06 13:09:06 【问题描述】:我无法在我的 QML TableView 上显示数据。我已经定义了两个数组——我想在 TableView 上显示的标题和行,但到目前为止没有成功。下面是最小的可重现示例。
engine.py
import os
import sys
from PySide2 import QtCore, QtGui, QtSql, QtQml
from Table import TbModel
from PySide2.QtWidgets import QApplication
if __name__ == "__main__":
current_dir = os.path.dirname(os.path.realpath(__file__))
app = QApplication(sys.argv)
QtQml.qmlRegisterType(TbModel, "TbModel", 1, 0, "TbModel")
engine = QtQml.QQmlApplicationEngine()
qml_path = os.path.join( "main.qml")
engine.load(QtCore.QUrl.fromLocalFile(qml_path))
if not engine.rootObjects():
sys.exit(-1)
sys.exit(app.exec_())
main.qml
import QtQuick 2.13
import QtQuick.Window 2.2
import QtQuick.Controls 2.5
import QtQuick.Controls 1.4
import QtQuick.Controls 2.13
import TbModel 1.0
ApplicationWindow
visible: true
id: window
width: Screen.width
height: Screen.height
Grid
width: 300
height: 100
visible: true
spacing: 200
TableView
id: idtable
model: TbModel
TableViewColumn
role: "sci"
title: "sci"
TableViewColumn
role: "year"
title: "year"
TableViewColumn
role: "cont"
title: "cont"
// Component.onCompleted:
// var roles = model.roleNameArray()
// for (var i = 0; i < model.columnCount(); i++)
//
// var column = addColumn( Qt.createQmlObject(
// "import QtQuick.Controls 1.1; TableViewColumn ",
// this) )
// column.role=roles[i]
// column.title=roles[i]
//
//
表格.py
from PySide2.QtCore import QAbstractTableModel, QModelIndex, QObject, Qt
from PySide2 import QtCore
class TbModel(QAbstractTableModel):
def __init__(self, parent: QObject = None) -> None:
super().__init__(parent)
self.headers = ["sci", "year", "cont"]
self.rows = [("Newton", "1643-01-04", "Classical mechanics"),
("Einstein", "1879-03-14", "Relativity"),
("Darwin", "1809-02-12", "Evolution")]
def rowCount(self, parent=QModelIndex()):
return len(self.rows)
def columnCount(self, parent=QModelIndex()):
return len(self.headers)
def data(self, index, role):
if role != Qt.DisplayRole:
return None
return self.rows[index.row()][index.column()]
def headerData(self, section, orientation, role) :
if role != Qt.DisplayRole:
return None
if section < 0 or section >= len(self.headers):
return None
return self.headers[section]
def roleNames(self):
roles =
Qt.UserRole + 1 : 'sci',
Qt.UserRole + 2 : 'year',
Qt.UserRole + 3 : 'cont'
return roles
@QtCore.Slot(result="QVariantList")
def roleNameArray(self):
names = []
names=self.headers
return names
我可以在 TableView 中选择行,但看不到数据。任何帮助表示赞赏。
【问题讨论】:
我只看C++ example。您没有尝试实现QHash<int, QByteArray> roleNames() const override
及其示例中描述的用法吗?当然,以某种 python 方式。我的意思是用Text text: display
替换代表?另外我会尝试将角色名称替换为一些符号而不是数字。
我认为你是对的,我通过实现 roleNames() 和手动插入 TableColumns 来编辑代码,但表格仍然是空的。
我猜你也必须更新data()
。我的意思是应该为每个角色返回适当的值。现在您忽略除 Qt.DisplayRole
之外的所有角色,但有时您声明角色 >= Qt.UserRole + 1。headerData()
也是如此。
我实施了您的解决方案,它在一定程度上有所帮助。我将数据写入表,但只有第一行的数据 Newton
, Einstein
, Darwin
写入所有 3 列。我试图自己弄清楚这一点,这就是反馈延迟的原因。已实施解决方案的代码已被编辑。
@user2727167 1) 如果解决方案不正确,那么您需要立即获得反馈,因为该解决方案不仅适用于您,而且适用于整个社区。 2)如果您有解决方案,请不要将其放在您的问题中,而是要创建一个答案。请使用@username
。所以我做了一个回滚,另一方面你的版本清楚地实现了我的解决方案,你的解决方案和我的有什么区别?阅读How to Ask、How to Answer 并查看tour
【参考方案1】:
您的代码有 2 个错误:
在 C++ 中,roleNames()
方法返回 QHash<int, QByteArray>
,因此在 Python 中,您必须返回其键是整数且值必须是 bytes
或 QByteArray
的字典,但在您的情况下,值是字符串。
数据方法必须提供视图所需的信息,在这种情况下,它们是与“sci”、“year”和“cont”关联的角色,其值为Qt.UserRole + 1
、Qt.UserRole + 2
和Qt.UserRole + 3
与 Qt.DisplayRole
不同,但在您的逻辑中,除 Qt.DisplayRole
之外的任何值都将为 None 与上述内容相矛盾。
QML 提供了几个 TableView:QtQuick.Controls 1.x 和 QtQuick。在您的情况下,您使用的第一个模型不需要 QAbstractTableModel 而只需要一个 QAbstractListModel,因为视图使用的 QModelIndex 的列值始终为 1。
考虑到上述情况,您可能会遇到问题,因为 QML 提供了多个属于不同包的同名项目,为了解决这个问题,使用了命名空间。
综合以上情况,解决办法是:
from PySide2.QtCore import QAbstractListModel, QModelIndex, QObject, Qt, Slot
class TbModel(QAbstractListModel):
def __init__(self, parent: QObject = None) -> None:
super().__init__(parent)
self.headers = ["sci", "year", "cont"]
self.rows = [
("Newton", "1643-01-04", "Classical mechanics"),
("Einstein", "1879-03-14", "Relativity"),
("Darwin", "1809-02-12", "Evolution"),
]
def rowCount(self, parent=QModelIndex()):
return len(self.rows)
def data(self, index, role=Qt.DisplayRole):
row = index.row()
if 0 <= row < self.rowCount():
if role in self.roleNames():
name_role = self.roleNames()[role].decode()
col = self.headers.index(name_role)
return self.rows[row][col]
def headerData(self, section, orientation, role):
if role == Qt.DisplayRole and 0 <= section < len(self.headers):
return self.headers[section]
def roleNames(self):
roles =
for i, header in enumerate(self.headers):
roles[Qt.UserRole + i + 1] = header.encode()
return roles
@Slot(result="QVariantList")
def roleNameArray(self):
return self.headers
import QtQuick 2.13
import QtQuick.Window 2.13
import QtQuick.Controls 1.4 as QQC1
import TbModel 1.0
QQC1.ApplicationWindow
id: window
visible: true
width: Screen.width
height: Screen.height
QQC1.TableView
id: idtable
width: 600
height: 300
model: TbModel
QQC1.TableViewColumn
role: "sci"
title: "sci"
QQC1.TableViewColumn
role: "year"
title: "year"
QQC1.TableViewColumn
role: "cont"
title: "cont"
输出:
【讨论】:
以上是关于TableView重新实现QAbstractTableModel后表中没有数据显示的主要内容,如果未能解决你的问题,请参考以下文章
使用 Xib 在 Tableview Header 中快速重新加载 CollectionView
重新启动应用程序后tableview不显示tableview中的所有数据
如何在 swift 中使用 fetchedresultscontroller 重新排序 tableview 行?
使用新的 iOS 11 API 重新排序 tableview 时动画不正确