Tableview aktualisieren

Python und das Qt-Toolkit, erstellen von GUIs mittels des Qt-Designers.
Antworten
Auerhahn
User
Beiträge: 31
Registriert: Dienstag 23. Juli 2019, 06:48

Ich habe eine Tabelle, die mit einer Datenbank verbunden ist. Da ich mehrzeiligen Text in die Felder eingeben muss, verwende ich (per Delegate) QPlainTextedit als Editor. Das funktioniert alles sehr gut, der Editor wird richtig aufgerufen, ich kann den Eintrag bearbeiten, und er wird in der Datenbank aktualisiert. Allerdings sehe ich das erst, nachdem ich zu einer anderen Zeile gewechselt bin. Vorher sieht das Feld wie vor der Bearbeitung. Das liegt offensichtlich daran, dass die Darstellung nach dem Schließen des Editors nicht aktualisiert, also mit der Datenbank abgeglichen wird. Ich finde beim besten Willen keine Möglichkeit, das zu erreichen, wobei ich annehme, dass es unproblematisch ist und ich einfach Tomaten auf den Augen habe. Kann mir die jemand wegnehmen?
__deets__
User
Beiträge: 14537
Registriert: Mittwoch 14. Oktober 2015, 14:29

Was fuer ein Modell unterliegt dem View? Oder ist der ohne Modell genutzt?
Auerhahn
User
Beiträge: 31
Registriert: Dienstag 23. Juli 2019, 06:48

Das ist QSqlTableModel. Wie gesagt: Im Grunde geht alles gut, nur die Anzeige wird erst aktualisiert, wenn ich ein anderes Feld auswähle. Wenn ich submit() und select() zur Anwendung bringe (z. B. von einem Schalter aus), ist alles in Ordnung. Aber das ist keine sinnvolle Lösung. Das Problem ist aus meiner Sicht, dass die Anzeige nicht weiß, dass sich etwas geändert hart. Und ich finde keine Möglichkeit, das mitzuteilen.
__deets__
User
Beiträge: 14537
Registriert: Mittwoch 14. Oktober 2015, 14:29

Wie Updatest du die DB denn konkret? Und das hier gesehen? https://doc.qt.io/qt-6/qsqltablemodel.h ... ategy-enum
Auerhahn
User
Beiträge: 31
Registriert: Dienstag 23. Juli 2019, 06:48

Ja, das kenne ich, habe ich auch eingestellt. Genauer: ich habe alle Einstellungen durchprobiert, das ändert nichts.
Die Daten werden in einer TableView angezeigt, mit einem Doppelklick öffnet sich erwartungsgemäß der Editor, den ich per Delegate eingestellt habe (QPlainTextedit). Ich kann die Daten problemlos bearbeiten, und die aktualisierten Daten werden in die Datenbank geschrieben, wenn ich den Editor schließe. Aber die Anzeige wird nur aktualisiert, wenn ich mit der Maus ein anderes Feld auswähle. Mir wäre lieb, wenn das automatisch geschehen würde.
__deets__
User
Beiträge: 14537
Registriert: Mittwoch 14. Oktober 2015, 14:29

Dann braucht’s ein minimales, Lauffähiges Beispiel, um das nachzuvollziehen. Oft löst das sogar schon das Problem, weil man daran Unterschiede herausarbeitet.
Auerhahn
User
Beiträge: 31
Registriert: Dienstag 23. Juli 2019, 06:48

Ich schaue mal, ob ich was zustande kriege. Daher die Frage ist ja nicht, was da vielleicht falsch ist, denn es funktioniert ja im Prinzip, wie es soll, sondern wie ich es erreiche, dass die Anzeige aktualisiert wird.
__deets__
User
Beiträge: 14537
Registriert: Mittwoch 14. Oktober 2015, 14:29

Das habe ich schon verstanden. Aber laut Dokumentation soll es genau so wie von dir gewünscht funktionieren. Wenn es das nicht tut, hat Qt einen Bug, oder du machst etwas komisch. Und was genau da passiert, kann man eben nur mit einem Beispiel nachvollziehen.
Auerhahn
User
Beiträge: 31
Registriert: Dienstag 23. Juli 2019, 06:48

Also kleiner kriege ich es nicht. Soll ich auch die UI-Datei mitschicken? Und auch einen Auszug aus der Datenbank?

Das ist übrigens alles noch ganz provisorisch zusammengestöpselt, um mal zu sehen, ob sich das überhaupt machen lässt. Also nicht zu genau hinsehen... ;)

Code: Alles auswählen

import sys
from Hauptfenster_neu import Ui_MainWindow
from PySide6 import QtGui, QtCore
from PySide6.QtSql import QSqlDatabase, QSqlTableModel
from PySide6.QtCore import Qt, Slot
from PySide6.QtWidgets import (
    QApplication,
    QMainWindow,
    QPlainTextEdit,
    QStyledItemDelegate,
)

db = QSqlDatabase("QSQLITE")
db.setDatabaseName("Datenbank.sqlite3")
db.open()

class MeinPlainTextEdit(QPlainTextEdit):
    def __init__(self, parent):
        super().__init__(parent)
        QtGui.QShortcut(QtGui.QKeySequence("Ctrl+Return"), self, self.close, context=QtCore.Qt.WidgetShortcut)

class ItemDelegate(QStyledItemDelegate):
    def createEditor(self, parent, option, index):
        return MeinPlainTextEdit(parent)

    @Slot()
    def stateChanged(self):
        self.commitData.emit(self.sender())


class Model(QSqlTableModel):
    def data(self, index, role):
        if role == Qt.TextAlignmentRole and (
                (index.column() == self.fieldIndex('Deutsch')) or (index.column() == self.fieldIndex('Englisch'))):
            return int(Qt.AlignmentFlag.AlignHCenter | Qt.AlignmentFlag.AlignBottom)
        else:
            return super().data(index, role)

class MainWindow(QMainWindow, Ui_MainWindow):
    def __init__(self):
        super().__init__()
        self.setupUi(self)

        self.model = Model(db=db)
        self.model.setTable("Die Tabelle")
        self.model.select()
        self.model.OnFieldChange = True

        self.tabelle.setModel(self.model)
        self.tabelle.setItemDelegateForColumn(2, ItemDelegate(self.tabelle))
        self.tabelle.setItemDelegateForColumn(3, ItemDelegate(self.tabelle))

app = QApplication(sys.argv)
window = MainWindow()

window.show()
app.exec()

Ich muss sicherlich nicht dazusagen, dass ich kein Profi bin. Das soll auch keine große Sache werden, nur ein kleines Werkzeug, mit dem ich mir und Kollegen einige langweilige und nervtötende Arbeiten erleichtern kann. Einige Erfahrung im Programmieren habe ich schon gesammelt und auch einige durchaus nützliche Sachen zustande gebracht (u.a. ein Vokabellernprogramm, damals noch mit Turbo-Pascal, dann mit Delphi, das mir beim Erlernen des Rumänischen und des Spanischen sehr gute Dienste geleistet hat)...

Wenn es einen Tip gibt, wie ich das lösen kann...

Übrigens wird der andere Editor gebraucht, weil die Texte bis zu zwei Zeilen enthalten können, die man mit der normalen QTableView nicht eingeben kann. Daher der ganze Umstand...
__deets__
User
Beiträge: 14537
Registriert: Mittwoch 14. Oktober 2015, 14:29

Laut Doku muss man setModelData implementieren, sieh zb hier: https://github.com/pyside/Examples/blob ... te.py#L123

MeinPlainTextEdit ist überflüssig, die Action kannst du genauso gut im delegate verknüpfen. Woher kommt stateChanged?

Wie gesagt, gewünscht ist eigentlich ein alleine lauffähiges Beispiel. Nicht ein runter editieren, bei dem man hofft, dass das schon so passt.
Auerhahn
User
Beiträge: 31
Registriert: Dienstag 23. Juli 2019, 06:48

Ja, das verstehe ich. Aber das kriege ich nicht hin. Dann kommen wir eben nicht weiter. Davon geht die Welt nicht unter.
Benutzeravatar
snafu
User
Beiträge: 6740
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

Versuche doch mal, den relevanten Teil deiner Daten testweise als verschachtelte Dicts zu implementieren. Dann könntest du um diese Daten ein eigenes Model bauen und schauen, ob die Aktualisierung damit wie gewünscht funktioniert. Zum einen könnte man dann besser einschätzen, ob das Problem durch die DB-Abfragen entsteht oder eben erst viel näher am View auftritt. Und es wäre leichter für andere nachvollziehbar, weil wir die Daten dann als reinen Python-Code sehen könnten.
__deets__
User
Beiträge: 14537
Registriert: Mittwoch 14. Oktober 2015, 14:29

Da der Verwandte View explizit mit SQL arbeitet, hilft das denke ich nicht. Wenn dann die Daten in eine sqlite zu stopfen.
Auerhahn
User
Beiträge: 31
Registriert: Dienstag 23. Juli 2019, 06:48

Ich habe das Beispiel mit dem Stardelegate, das ich schon oft betrachtet habe, dank Deines Hinweises diesmal endlich verstanden bzw. verstanden, inwiefern es mir weiterhelfen kann, und das Problem gelöst. Weitere harren nun der Bearbeitung, aber da sehe ich keine großen Schwierigkeiten. Besten Dank!
Antworten