无法在 QML TableView 中显示来自 QSqlQueryModel 的数据 [英] Can't display data from QSqlQueryModel in a QML TableView
问题描述
我试图在 QML 的 TableView
组件的帮助下,在表中显示来自 MySQL 数据库的数据.
I'm trying to display data from a MySQL database in a table with the help of TableView
component of QML.
最初我尝试从 QSqlQuery
对象创建一个 QSqlQueryModel
对象,并将其作为属性传递给 QML 上下文.但我从 Qt 文档 中了解到我必须实现 roleNames()
以提供列到角色映射到 TableView
,所以我像这样子类化 QSqlQueryModel
Initially I tried making a QSqlQueryModel
object from a QSqlQuery
object and pass it to QML context as a property. But I came to know from Qt documentation that I must implement roleNames()
to supply column to role mapping to TableView
, so I subclassed QSqlQueryModel
like so
import sys
from PyQt5.QtCore import QUrl, Qt
from PyQt5.QtGui import QGuiApplication
from PyQt5.QtQuick import QQuickView
from PyQt5.QtSql import QSqlDatabase, QSqlQuery, QSqlQueryModel
class QtTabModel(QSqlQueryModel):
def __init__(self):
super(QtTabModel, self).__init__()
@staticmethod
def roleNames():
roles = {
Qt.UserRole + 1 : "id",
Qt.UserRole + 2 : "name"
}
return roles
app = QGuiApplication(sys.argv)
view = QQuickView()
db = QSqlDatabase.addDatabase("QMYSQL")
db.setHostName("localhost")
db.setDatabaseName("qtdb")
db.setUserName("abc")
db.setPassword("xyz")
qry = QSqlQuery()
if db.open():
qry = db.exec("SELECT id, name FROM qttab")
tabmodel = QtTabModel()
tabmodel.setQuery(qry)
ctx = view.rootContext()
ctx.setContextProperty("tabmodel", tabmodel)
view.setSource(QUrl.fromLocalFile("sqltabletest.qml"))
view.show()
app.exec()
我的 QML 是
import QtQuick 2.2
import QtQuick.Controls 1.1
TableView {
width: 200
height: 300
model: tabmodel
}
但它什么也没显示,只是一个空白窗口
but it's showing nothing, just a blank window
我可以看到我的 QSqlQuery
正在工作,因为我可以使用该查询中的 value(n)
方法从数据库打印数据.我还检查了使 rolenames()
成员函数,但最终结果是一样的.
I can see my QSqlQuery
is working as I can print data from database using value(n)
method from that query. I've also checked with making rolenames()
member function, but the end result is same.
def roleNames(self):
roles = {
Qt.UserRole + 1 : "id",
Qt.UserRole + 2 : "name"
}
return roles
更新:
QSqlQueryModel
适用于小部件类,我已经用 QTableView
小部件对其进行了测试.但我需要让它与 QML 一起工作.
Update:
QSqlQueryModel
works with widget classes, I've tested it with QTableView
widget. But I need to make it work with QML.
import sys
from PyQt5.QtCore import Qt
from PyQt5.QtWidgets import QApplication, QTableView
from PyQt5.QtSql import QSqlDatabase, QSqlQuery, QSqlQueryModel
app = QApplication(sys.argv)
db = QSqlDatabase.addDatabase("QMYSQL")
db.setHostName("localhost")
db.setDatabaseName("qtdb")
db.setUserName("abc")
db.setPassword("xyz")
qry = QSqlQuery()
if db.open():
qry = db.exec("SELECT id, name FROM qttab")
tabmodel = QSqlQueryModel()
tabmodel.setQuery(qry)
tabmodel.setHeaderData(0, Qt.Horizontal, "ID")
tabmodel.setHeaderData(1, Qt.Horizontal, "Name")
tabview = QTableView()
tabview.setModel(tabmodel)
tabview.show()
db.close()
app.exec()
谁能帮我解决这个问题?提前致谢.
Can anyone please help me to resolve this issue? Thanks in advance.
推荐答案
好的,你的评论提醒我,为了 QML 的模型,你确实需要重新实现 data()
.为什么?因为 QML 的模型使用 roleName() 给出的角色调用 data()
.它不像在 QWidget 世界中那样使用 Qt::DisplayRole
调用 data()
.此外,您需要使用角色名称定义TableViewColumn
,否则模型将不会调用data()
.下面是一个如何重新实现 data()
的示例:
Ok, your comment reminded me that you indeed need to reimplement data()
for the sake of QML's model. Why? Because QML's model calls data()
with the roles given by roleName(). It doesn't call data()
with Qt::DisplayRole
like in QWidget world. Furthermore, you need to define TableViewColumn
with role names, otherwise model will not call data()
. Here's an example of how you can reimplement data()
:
import sys
from PyQt5.QtCore import QUrl, Qt, QVariant
from PyQt5.QtCore import QObject, pyqtSlot
from PyQt5.QtGui import QGuiApplication
from PyQt5.QtQuick import QQuickView
from PyQt5.QtSql import QSqlDatabase, QSqlQuery, QSqlQueryModel
class QtTabModel(QSqlQueryModel):
def __init__(self):
super(QtTabModel, self).__init__()
def roleNames(self):
roles = {
Qt.UserRole + 1 : 'id',
Qt.UserRole + 2 : 'name'
}
return roles
def data(self, index, role):
if role < Qt.UserRole:
# caller requests non-UserRole data, just pass to papa
return super(QtTabModel, self).data(index, role)
# caller requests UserRole data, convert role to column (role - Qt.UserRole -1) to return correct data
return super(QtTabModel, self).data(self.index(index.row(), role - Qt.UserRole -1), Qt.DisplayRole)
@pyqtSlot(result=QVariant) # don't know how to return a python array/list, so just use QVariant
def roleNameArray(self):
# This method is used to return a list that QML understands
list = []
# list = self.roleNames().items()
for key, value in self.roleNames().items():
list.append(value)
return QVariant(list)
将 TableViewColumn
添加到 TableView
.请记住,角色区分大小写.它们必须与 roleNames() 返回的内容完全匹配:
Add TableViewColumn
to TableView
. Keep in mind that role are case-sensitive. They must match exactly with what roleNames() returns:
import QtQuick 2.2
import QtQuick.Controls 1.1
TableView {
width: 200
height: 300
model: tabmodel
TableViewColumn {
role: "id" // case-sensitive, must match a role returned by roleNames()
}
TableViewColumn {
role: "name"
}
}
这里介绍一种自动生成TableViewColumn的方法.它调用上面python代码中定义的roleNameArray槽来获取角色名称列表.我们在这里不调用 roleNames() 因为我不知道如何让 QML 理解它返回的结果:),所以我们必须将它转换为列表.最后我们遍历列表并调用 TableView.addColumn 来创建列:
Here's a way to automatically generate TableViewColumn. It calls roleNameArray slot defined in python code above to get the role name list. We don't call roleNames() here since I don't know how to make QML understand the result it returns :), so we have to convert it to a list. Finally we loop through the list and call TableView.addColumn to create columns:
TableView {
width: 200
height: 300
model: tabmodel
Component.onCompleted: {
var roles = model.roleNameArray()
for (var i=0; i<roles.length; i++) {
var column = addColumn( Qt.createQmlObject(
"import QtQuick.Controls 1.1; TableViewColumn {}",
this) )
column.role = roles[i]
column.title = roles[i]
}
}
}
这篇关于无法在 QML TableView 中显示来自 QSqlQueryModel 的数据的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!