编辑添加的数据到 sublcassed QSqlQueryModel?

edit added data to sublcassed QSqlQueryModel?

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

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,我就是这样做的

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

应考虑以下因素:

  • 如果要显示来自 table 的信息,则必须使用 QSqlTableModel。 QSqlQueryModel 是一个只读模型,其 objective 用于显示非常特殊的查询信息。另一方面,QSqlTableModel 有几种方法来处理 tables.

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

综合以上,解决方案是:

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