简体   繁体   English

无法在QML TableView中显示来自QSqlQueryModel的数据

[英]Can't display data from QSqlQueryModel in a QML TableView

I'm trying to display data from a MySQL database in a table with the help of TableView component of QML. 我正在尝试借助QML的TableView组件在表中显示MySQL数据库中的数据。

Initially I tried making a QSqlQueryModel object from a QSqlQuery object and pass it to QML context as a property. 最初我试图使一个QSqlQueryModel从对象QSqlQuery对象并将其传递给QML上下文作为属性。 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 但是我从Qt文档中了解到,我必须实现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()

and my QML is 而我的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 但什么也没显示,只是一个空白窗口

Ubuntu 14.04中来自Qt5的空白窗口

I can see my QSqlQuery is working as I can print data from database using value(n) method from that query. 我可以看到我的QSqlQuery正在运行,因为我可以使用该查询中的value(n)方法从数据库中打印数据。 I've also checked with making rolenames() member function, but the end result is same. 我还检查了使rolenames()成员函数,但最终结果是相同的。

def roleNames(self):
    roles = {
        Qt.UserRole + 1 : "id",
        Qt.UserRole + 2 : "name"
    }
    return roles

Update: 更新:

QSqlQueryModel works with widget classes, I've tested it with QTableView widget. QSqlQueryModel适用于小部件类,我已经使用QTableView小部件对其进行了测试。 But I need to make it work with QML. 但是我需要使其与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()

有效的Qt5代码

Can anyone please help me to resolve this issue? 谁能帮我解决这个问题? Thanks in advance. 提前致谢。

Ok, your comment reminded me that you indeed need to reimplement data() for the sake of QML's model. 好的,您的评论提醒我,为了QML的模型,您确实确实需要重新实现data() Why? 为什么? Because QML's model calls data() with the roles given by roleName(). 因为QML的模型使用由roleName()赋予的角色来调用data() ()。 It doesn't call data() with Qt::DisplayRole like in QWidget world. 它不会像QWidget世界中那样使用Qt::DisplayRole调用data() Furthermore, you need to define TableViewColumn with role names, otherwise model will not call data() . 此外,您需要使用角色名称定义TableViewColumn ,否则模型将不会调用data() Here's an example of how you can reimplement 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)

Add TableViewColumn to TableView . TableViewColumn添加到TableView Keep in mind that role are case-sensitive. 请记住,角色区分大小写。 They must match exactly with what roleNames() returns: 它们必须与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"
    }

}

Here's a way to automatically generate TableViewColumn. 这是一种自动生成TableViewColumn的方法。 It calls roleNameArray slot defined in python code above to get the role name list. 它调用上面python代码中定义的roleNameArray插槽,以获取角色名称列表。 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. 因为我不知道如何使QML理解返回的结果,所以我们这里不调用roleNames(),所以我们必须将其转换为列表。 Finally we loop through the list and call TableView.addColumn to create columns: 最后,我们遍历列表并调用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]
        }
    }

}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM