编辑添加的数据到 sublcased QSqlQueryModel?

Posted

技术标签:

【中文标题】编辑添加的数据到 sublcased QSqlQueryModel?【英文标题】:edit added data to sublcassed QSqlQueryModel? 【发布时间】:2020-12-12 10:43:19 【问题描述】:

我想在 QlistView 中显示索引和文件名,所以我将 QSqlQueryModel 子类化以覆盖 data() 方法,但我总是得到无,似乎我在添加数据之前显示数据或一些这样的事情是我的代码的相关部分:

from PyQt5.QtWidgets import *
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtSql import *

import sys, os
import pathlib

CURRENT_PATH = pathlib.Path(__file__).parent

connection = QSqlDatabase.addDatabase("QSQLITE")
connection.setDatabaseName("medias.sqlite")
connection.open()
print(connection.open())
createTableQuery = QSqlQuery()
createTableQuery.exec(
    """
    CREATE TABLE fichiers (
        id INTEGER PRIMARY KEY AUTOINCREMENT UNIQUE NOT NULL,
        path VARCHAR(300) NOT NULL
    )
    """
)
print(connection.tables())

class PlaylistModel(QSqlQueryModel):
    def __init__(self, playlist,*args, **kwargs):
        super(PlaylistModel, self).__init__(*args, **kwargs)
        self.playlist = playlist or  [[]]
    def data(self, index, role):
        row = index.row()
        if role == Qt.DisplayRole:
            try:
                text = self.playlist[index.row()][1]
            except IndexError:
                text = None
            return text  # always getting None

class MainWindow(QMainWindow):

    def __init__(self, *args, **kwargs):
        super(MainWindow, self).__init__(*args, **kwargs)
        self.play_list = []
        self.setGeometry(900,180,800,600)
        self.setWindowTitle("Media Display")
        self.model = PlaylistModel(self.play_list)
        self.model.setQuery("SELECT path FROM fichiers")
        
        self.listview = QListView()
        self.listview.setModel(self.model)
        self.listview.setModelColumn(1)
        self.main_layout()
        self.DbConnect()

    def DbConnect(self):
        self.connection = QSqlDatabase.addDatabase("QSQLITE")
        self.connection.setDatabaseName("medias.sqlite")
        self.connection.open()
        createTableQuery = QSqlQuery()
        createTableQuery.exec(
            """ CREATE TABLE fichiers (
            id INTEGER PRIMARY KEY AUTOINCREMENT UNIQUE NOT NULL,
            path VARCHAR(300) NOT NULL
            )
            """
            )
        self.model.setQuery("SELECT path FROM fichiers")
        return True

    def addToPlaylist(self):
        self.play_list.clear()
        model = self.listview.model()
        for row in range(model.rowCount()):
            index = model.index(row , 0)
            item = model.data(index, Qt.DisplayRole)
            self.play_list.append(item)
        print('the playlist',self.play_list)
    def addImage(self):
        fichier_base, _ = QFileDialog.getOpenFileName(self, 'select video', QDir.homePath(),"Images (*.png *.xpm *.jpg *.jpeg)")

        if fichier_base:
            query = QSqlQuery()
            query.prepare("""INSERT INTO fichiers (path) VALUES (?)""")
            query.addBindValue(fichier_base)
            if query.exec_():
                last_query = self.model.query().executedQuery()
                self.model.setQuery("")
                self.model.setQuery(last_query)

            else:
                print(query.lastError().text())
      
    def clearDb(self):
        query = QSqlQuery(self.connection)
        if self.connection.open():
            query.exec("DELETE FROM fichiers")
            query.clear()
            last_query = self.model.query().executedQuery()
            self.model.setQuery("")
            self.model.setQuery(last_query)

    def main_layout(self):

        self.add_img_btn = QPushButton("Add image ")
        self.add_img_btn.setFixedWidth(150)
        self.add_img_btn.clicked.connect(self.addImage)

        self.clear_db_btn = QPushButton("clear DB")
        self.clear_db_btn.setFixedWidth(150)
        self.clear_db_btn.clicked.connect(self.clearDb)

        self.refresh_btn = QPushButton("refresh")
        self.refresh_btn.setFixedWidth(150)
        self.refresh_btn.clicked.connect(self.addToPlaylist)

        group_btns = QHBoxLayout()

        main_app = QVBoxLayout()

        main_app.addWidget(self.listview)
        main_app.addLayout(group_btns)

        group_btns.addWidget(self.add_img_btn)
        group_btns.addWidget(self.clear_db_btn)
        group_btns.addWidget(self.refresh_btn)

        vboxlay = QHBoxLayout()
        vboxlay.addLayout(main_app)

        widget = QWidget(self)
        self.setCentralWidget(widget)
        widget.setLayout(vboxlay)

if __name__ == '__main__':
    app= QApplication(sys.argv)
    window = MainWindow()
    window.setStyleSheet('background-color:#fff;')
    window.show()
    sys.exit(app.exec_())

在以前的应用程序中,我将 QAbstractListModel 类子类化,然后我就这样做了

class PlaylistModel(QAbstractListModel):
    def __init__(self, playlist, *args, **kwargs):
        super(PlaylistModel, self).__init__(*args, **kwargs)
        self.playlist = playlist

    def data(self, index, role):
        if role == Qt.DisplayRole:
            media = self.playlist.media(index.row())
            print('mediaaaaaaa', media )
            print('plaaaaaylist', self.playlist )
            name_video = media.canonicalUrl().fileName()
            i = index.row() + 1
            return f"i -          name_video"

    def rowCount(self, index):
        return self.playlist.mediaCount()

【问题讨论】:

请提供minimal reproducible example 对不起,我编辑了上面的代码,我犯了一些错误,现在它正在工作,谢谢@eyllanesc 您还有帖子指出的问题吗?如果您不再遇到问题,那么您应该删除您的帖子 我仍然有问题,当我覆盖 QSqlQueryModel 类时,我无法显示我的数据,而是得到 None 我不明白你的目标是什么,你希望通过覆盖数据方法得到什么?为什么需要修改它?我认为你有一个XY问题。据我所知,默认情况下 QSqlQueryModel 会显示文件的路径,而您希望它显示索引,例如number of row - path_of_file,对吗? 【参考方案1】:

应考虑以下几点:

如果要显示表中的信息,则必须使用 QSqlTableModel。 QSqlQueryModel 是一个只读模型,其目标是显示非常特殊的查询信息。另一方面,QSqlTableModel 有几种处理表格的方法。

如果您要修改模型信息在视图中的显示方式,则必须使用委托。这使得修改更加灵活,因为您可以让不同的模型对视图应用相同的修改。

综合以上情况,解决办法是:

import sys

from PyQt5.QtCore import QDir
from PyQt5.QtSql import QSqlDatabase, QSqlTableModel, QSqlQuery
from PyQt5.QtWidgets import (
    QApplication,
    QFileDialog,
    QHBoxLayout,
    QListView,
    QMainWindow,
    QPushButton,
    QStyledItemDelegate,
    QVBoxLayout,
    QWidget,
)


def create_connection():
    db = QSqlDatabase.addDatabase("QSQLITE")
    db.setDatabaseName("medias.sqlite")
    if not db.open():
        print(db.lastError().text())
        return False

    q = QSqlQuery()
    if not q.exec(
        """
    CREATE TABLE IF NOT EXISTS fichiers (
        id INTEGER PRIMARY KEY AUTOINCREMENT UNIQUE NOT NULL,
        path VARCHAR(300) NOT NULL
    )
    """
    ):
        print(q.lastError().text())
        return False
    print(db.tables())
    return True


class StyledItemDelegate(QStyledItemDelegate):
    def initStyleOption(self, option, index):
        super().initStyleOption(option, index)
        option.text = f"index.row() + 1 -          index.data()"


class MainWindow(QMainWindow):
    def __init__(self, *args, **kwargs):
        super(MainWindow, self).__init__(*args, **kwargs)
        self.play_list = []
        self.setGeometry(900, 180, 800, 600)
        self.setWindowTitle("Media Display")

        self.model = QSqlTableModel()
        self.model.setTable("fichiers")
        self.model.select()

        self.listview = QListView()
        delegate = StyledItemDelegate(self.listview)
        self.listview.setItemDelegate(delegate)
        self.listview.setModel(self.model)
        self.listview.setModelColumn(1)

        self.init_ui()

    def addImage(self):
        fichier_base, _ = QFileDialog.getOpenFileName(
            self, "select video", QDir.homePath(), "Images (*.png *.xpm *.jpg *.jpeg)"
        )

        if fichier_base:
            rec = self.model.record()
            rec.setValue("path", fichier_base)
            self.model.insertRecord(-1, rec)
            self.model.select()

    def clearDb(self):
        query = QSqlQuery()
        query.exec("DELETE FROM fichiers")
        self.model.select()

    def init_ui(self):

        self.add_img_btn = QPushButton("Add image ")
        self.add_img_btn.setFixedWidth(150)
        self.add_img_btn.clicked.connect(self.addImage)

        self.clear_db_btn = QPushButton("clear DB")
        self.clear_db_btn.setFixedWidth(150)
        self.clear_db_btn.clicked.connect(self.clearDb)

        self.refresh_btn = QPushButton("refresh")
        self.refresh_btn.setFixedWidth(150)

        group_btns = QHBoxLayout()

        main_app = QVBoxLayout()

        main_app.addWidget(self.listview)
        main_app.addLayout(group_btns)

        group_btns.addWidget(self.add_img_btn)
        group_btns.addWidget(self.clear_db_btn)
        group_btns.addWidget(self.refresh_btn)

        widget = QWidget()
        vboxlay = QHBoxLayout(widget)
        vboxlay.addLayout(main_app)

        self.setCentralWidget(widget)


if __name__ == "__main__":
    app = QApplication(sys.argv)

    if not create_connection():
        sys.exit(-1)
    window = MainWindow()
    window.setStyleSheet("background-color:#fff;")
    window.show()
    sys.exit(app.exec_())

【讨论】:

非常感谢,我不知道

以上是关于编辑添加的数据到 sublcased QSqlQueryModel?的主要内容,如果未能解决你的问题,请参考以下文章

在uwp中向数据网格添加新行时如何自动开始编辑?

将表数据添加到可编辑的 DataTables 会删除过滤器

在更新到数据库之前编辑 DataTable 中的行

如何把kindEditor编辑好的内容添加到mysql数据库中

简易点菜系统

vc++6.0如何实现在模态对话框编辑框中输入数据,单击确定按钮将数据添加到组合框按钮中!