为了账号安全,请及时绑定邮箱和手机立即绑定

PySide2 SQLITE 表视图

PySide2 SQLITE 表视图

萧十郎 2022-06-02 10:39:40
在尝试QSQLITE在 QML 中显示表中的数据时,TableView我偶然发现了这个答案并试图跟进它。我理解重新实施的必要性,data()但是roleNames()当涉及到QVariantPySide2 中不存在的问题时,我遇到了问题。我明白了NameError: name 'QVariant' is not defined。我已经测试了从数据库读取数据,它的工作。是否有任何数据类型可以代替QVariantPySide2 使用?我的计划是拥有来自不同表的多个数据源。这个例子使用setContextProperty,在这种情况下使用是更好的做法qmlRegisterType吗?文件夹结构├── ViewModel│   └── QCond.py├── Qml│   └── Modellist.qml└── qmlengine.pyqmlengine.pyimport osimport sysfrom PySide2.QtCore import QUrl, QStringListModel, QCoreApplication, Qtfrom PySide2.QtGui import QGuiApplicationfrom PySide2.QtQml import QQmlApplicationEngine, qmlRegisterTypefrom PySide2.QtSql import QSqlDatabase, QSqlQuery, QSqlQueryModelfrom 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.pyimport sysfrom PySide2 import QtCore, QtGui, QtQmlfrom PySide2.QtCore import QObject, Qt,Signal, Slot, QUrl, QStringListModel, QCoreApplicationimport sqlite3from PySide2.QtSql import QSqlDatabase, QSqlQuery, QSqlQueryModelclass 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)任何帮助表示赞赏。提前致谢。
查看完整描述

1 回答

?
MMTTMM

TA贡献1869条经验 获得超4个赞

在您的情况下,roleNameArray 返回一个列表,正如我在这个答案中指出的那样,您必须使用“QVariantList”。另一方面,我通过根据我的旧答案概括示例来改进示例:(1),(2),考虑到解决方案是:

├── db

│   └── CatData.db

├── qml

│   └── Modellist.qml

├── qmlengine.py

└── ViewModel

    └── model.py

视图模型/model.py


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/模型列表.qml


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


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_()) 

输出:

//img1.sycdn.imooc.com//6298232c00016a9d10310754.jpg

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


视图模型/model.py


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/模型列表.qml


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


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_())


查看完整回答
反对 回复 2022-06-02
  • 1 回答
  • 0 关注
  • 205 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信