我试图在QML的TableView
组件的帮助下在表中显示MySQL数据库中的数据。
最初我尝试从QSqlQueryModel
对象创建一个QSqlQuery
对象,并将其作为属性传递给QML上下文。但是我从Qt documentation开始知道我必须实现roleNames()
以提供列到角色映射到TableView
的列,所以我将QSqlQueryModel
分类为
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
}
但它没有显示任何内容,只是一个空白窗口
我可以看到我的QSqlQuery
正在运行,因为我可以使用该查询中的value(n)
方法从数据库打印数据。我还检查过制作rolenames()
成员函数,但最终结果是一样的。
def roleNames(self):
roles = {
Qt.UserRole + 1 : "id",
Qt.UserRole + 2 : "name"
}
return roles
QSqlQueryModel
适用于小部件类,我已使用QTableView
小部件对其进行了测试。但我需要让它与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()
有人可以帮我解决这个问题吗?提前谢谢。
答案 0 :(得分:4)
好的,您的评论提醒我,您确实需要为QML的模型重新实现data()
。为什么?因为QML的模型使用roleName()给出的角色调用data()
。它不像QWidget世界那样用data()
调用Qt::DisplayRole
。此外,您需要使用角色名称定义TableViewColumn
,否则模型将不会调用data()
。以下是如何重新实现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()返回的内容完全匹配:
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来创建列:
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]
}
}
}