首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >PySide2 SQLITE TableView

PySide2 SQLITE TableView
EN

Stack Overflow用户
提问于 2019-09-22 17:36:51
回答 1查看 1.7K关注 0票数 1

在试图在QML QSQLITE TableView中显示来自TableView表的数据时,我无意中发现了这个答案,并试图对其进行跟踪。我理解重新实现data()roleNames()的必要性,但是当涉及到PySide2中不存在的QVariant时,我遇到了问题。我得到了NameError: name 'QVariant' is not defined。我测试过从数据库中读取数据,它的工作原理。是否有任何数据类型可以代替QVariant在PySide2中使用?我的计划是让来自不同tables.This示例的多个数据源使用setContextProperty,在这种情况下使用qmlRegisterType更好吗?

SQLITE数据库

文件夹结构

代码语言:javascript
复制
├── ViewModel
│   └── QCond.py
├── Qml
│   └── Modellist.qml
└── qmlengine.py

qmlengine.py

代码语言:javascript
复制
import os
import sys
from PySide2.QtCore import QUrl, QStringListModel, QCoreApplication, Qt
from PySide2.QtGui import QGuiApplication
from PySide2.QtQml import QQmlApplicationEngine, qmlRegisterType
from PySide2.QtSql import QSqlDatabase, QSqlQuery, QSqlQueryModel
from ViewModel.QCond import *
if __name__ == "__main__":
    app = QGuiApplication(sys.argv)
    engine = QQmlApplicationEngine()
    db = QSqlDatabase.addDatabase("QSQLITE")
    db.setDatabaseName("C:\\Users\\terao\\Documents\\ctmd\\CatData.db")
    db.open()
    qry = QSqlQuery()
    qry=db.exec_("SELECT tip,s FROM uzad")
    tabmodel = QtCond()
    tabmodel.setQuery(qry)
    engine.rootContext().setContextProperty("tabmodel", tabmodel)
    engine.load(QUrl.fromLocalFile('Qml/Modellist.qml'))
    if not engine.rootObjects():
        sys.exit(-2)
    sys.exit(app.exec_())

QCond.py

代码语言:javascript
复制
import sys
from PySide2 import QtCore, QtGui, QtQml
from PySide2.QtCore import QObject, Qt,Signal, Slot, QUrl, QStringListModel, QCoreApplication
import sqlite3
from PySide2.QtSql import QSqlDatabase, QSqlQuery, QSqlQueryModel
class QtCond(QSqlQueryModel):
    def __init__(self):
        super(QtCond, self).__init__()

    def roleNames(self):
        roles = {
            Qt.UserRole + 1 : 'tip',
            Qt.UserRole + 2 : 's'
        }
        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)

    @QtCore.Slot(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(str(value))

        return QVariant(list)

Modellist.qml

代码语言:javascript
复制
import QtQuick 2.5
import QtQuick.Controls 1.4
import QtQuick.Controls 2.5

TableView {
    width: 1000
    height: 1000
    model: tabmodel
    TableViewColumn {
        role: "tip" // case-sensitive, must match a role returned by roleNames()
    }
    TableViewColumn {
        role: "s"
    }

}

任何帮助都是非常感谢的。提前谢谢。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2019-09-23 00:52:39

在您的示例中,roleNameArray返回一个列表,正如我在这个答案中指出的那样,您必须使用"QVariantList“。另一方面,我根据我以前的答案:(1),(2)对示例进行了改进,考虑到解决方案是:

代码语言:javascript
复制
├── db
│   └── CatData.db
├── qml
│   └── Modellist.qml
├── qmlengine.py
└── ViewModel
    └── model.py

ViewModel/model.py

代码语言:javascript
复制
from PySide2 import QtCore, QtSql


class SqlQueryModel(QtSql.QSqlQueryModel):
    def data(self, index, role=QtCore.Qt.DisplayRole):
        value = None
        if index.isValid():
            if role < QtCore.Qt.UserRole:
                value = super(SqlQueryModel, self).data(index, role)
            else:
                columnIdx = role - QtCore.Qt.UserRole - 1
                modelIndex = self.index(index.row(), columnIdx)
                value = super(SqlQueryModel, self).data(
                    modelIndex, QtCore.Qt.DisplayRole
                )
        return value

    def roleNames(self):
        roles = dict()
        for i in range(self.record().count()):
            roles[QtCore.Qt.UserRole + i + 1] = self.record().fieldName(i).encode()
        return roles

    @QtCore.Slot(result="QVariantList")
    def roleNameArray(self):
        names = []
        for i in range(self.record().count()):
            names.append(self.record().fieldName(i))
        return names

qml/Modellist.qml

代码语言:javascript
复制
import QtQuick 2.5
import QtQuick.Controls 1.4
import QtQuick.Controls 2.5

ApplicationWindow{
    width: 1000
    height: 1000
    visible: true

    TableView {
        anchors.fill: parent
        model: tabmodel

        /*TableViewColumn {
            role: "tip"
        }
        TableViewColumn {
            role: "s"
        }*/

        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]
            }
        }
    }
}

qmlengine.py

代码语言:javascript
复制
import os
import sys

from PySide2 import QtCore, QtGui, QtSql, QtQml

from ViewModel.model import SqlQueryModel

def create_connection(path):
    db = QtSql.QSqlDatabase.addDatabase('QSQLITE')
    db.setDatabaseName(path)
    if not db.open():
        print('''Unable to establish a database connection.\n
            This example needs SQLite support. Please read
            the Qt SQL driver documentation for information
            how to build it.\n\n Click Cancel to exit.''')
        return False
    return True

if __name__ == "__main__":
    current_dir = os.path.dirname(os.path.realpath(__file__))
    app = QtGui.QGuiApplication(sys.argv)
    engine = QtQml.QQmlApplicationEngine()
    db_path = os.path.join(current_dir, "db", "CatData.db")
    if not create_connection(db_path):
        sys.exit(-1)

    tabmodel = SqlQueryModel()
    tabmodel.setQuery("SELECT tip,s FROM uzad")
    engine.rootContext().setContextProperty("tabmodel", tabmodel)
    qml_path = os.path.join("qml", "Modellist.qml")
    engine.load(QtCore.QUrl.fromLocalFile(qml_path))
    if not engine.rootObjects():
        sys.exit(-2)
    sys.exit(app.exec_()) 

输出:

qmlRegisterType的目标是通过抽象源和实现在QML中注册Python/C++类型。在您的情况下,如果您想注册它,最好是查询qproperty,以便可以从QML访问它:

ViewModel/model.py

代码语言:javascript
复制
from PySide2 import QtCore, QtSql


class SqlQueryModel(QtSql.QSqlQueryModel):

    queryStrChanged = QtCore.Signal(str)

    def get_query_str(self):
        return self.query().lastQuery()

    def set_query_str(self, query):
        if self.get_query_str() == query:
            return
        self.setQuery(query)
        self.queryStrChanged.emit(query)

    query_str = QtCore.Property(
        str, fget=get_query_str, fset=set_query_str, notify=queryStrChanged
    )

    def data(self, index, role=QtCore.Qt.DisplayRole):
        value = None
        if index.isValid():
            if role < QtCore.Qt.UserRole:
                value = super(SqlQueryModel, self).data(index, role)
            else:
                columnIdx = role - QtCore.Qt.UserRole - 1
                modelIndex = self.index(index.row(), columnIdx)
                value = super(SqlQueryModel, self).data(
                    modelIndex, QtCore.Qt.DisplayRole
                )
        return value

    def roleNames(self):
        roles = dict()
        for i in range(self.record().count()):
            roles[QtCore.Qt.UserRole + i + 1] = self.record().fieldName(i).encode()
        return roles

    @QtCore.Slot(result="QVariantList")
    def roleNameArray(self):
        names = []
        for i in range(self.record().count()):
            names.append(self.record().fieldName(i))
        return names

qml/Modellist.qml

代码语言:javascript
复制
import QtQuick 2.5
import QtQuick.Controls 1.4
import QtQuick.Controls 2.5

import mycomponents 1.0

ApplicationWindow{
    width: 1000
    height: 1000
    visible: true

    SqlQueryModel{
        id: tabmodel
        query_str: "SELECT tip,s FROM uzad"
    }

    TableView {
        anchors.fill: parent
        model: tabmodel

        /*TableViewColumn {
            role: "tip"
        }
        TableViewColumn {
            role: "s"
        }*/

        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]
            }
        }
    }
}

qmlengine.py

代码语言:javascript
复制
import os
import sys

from PySide2 import QtCore, QtGui, QtSql, QtQml

from ViewModel.model import SqlQueryModel

def create_connection(path):
    db = QtSql.QSqlDatabase.addDatabase('QSQLITE')
    db.setDatabaseName(path)
    if not db.open():
        print('''Unable to establish a database connection.\n
            This example needs SQLite support. Please read
            the Qt SQL driver documentation for information
            how to build it.\n\n Click Cancel to exit.''')
        return False
    return True

if __name__ == "__main__":
    current_dir = os.path.dirname(os.path.realpath(__file__))
    QtQml.qmlRegisterType(SqlQueryModel, "mycomponents", 1, 0, "SqlQueryModel")
    app = QtGui.QGuiApplication(sys.argv)
    engine = QtQml.QQmlApplicationEngine()
    db_path = os.path.join(current_dir, "db", "CatData.db")
    if not create_connection(db_path):
        sys.exit(-1)
    qml_path = os.path.join("qml", "Modellist.qml")
    engine.load(QtCore.QUrl.fromLocalFile(qml_path))
    if not engine.rootObjects():
        sys.exit(-2)
    sys.exit(app.exec_())
票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/58051785

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档