无法在 QML TableView 中显示来自 QSqlQueryModel 的数据 [英] Can't display data from QSqlQueryModel in a QML TableView

查看:46
本文介绍了无法在 QML TableView 中显示来自 QSqlQueryModel 的数据的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图在 QML 的 TableView 组件的帮助下,在表中显示来自 MySQL 数据库的数据.

I'm trying to display data from a MySQL database in a table with the help of TableViewcomponent 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆