TableView QVariant Problem

Python und das Qt-Toolkit, erstellen von GUIs mittels des Qt-Designers.
Antworten
Mosquitsch
User
Beiträge: 8
Registriert: Donnerstag 3. November 2011, 09:50

Hallo,
das ist mein erster Beitrag und ich hoffe ihr könnt mir helfen.

Ich habe ein TableView Objekt, das editierbar ist. Sobald ich in der zweiten Spalte einen Wert ändere und die Werte der gesamten Tabelle auslese wird mir das QVariant Objekt im speicher angezeigt: <PyQt4.QtCore.QVariant object at 0x06274110> <PyQt4.QtCore.QVariant object at 0x06274110>

Die Tabelle lese ich so aus:

Code: Alles auswählen

    def listData(self, role):
        
        if role == QtCore.Qt.DisplayRole:
            columns = len(self.__values[0])
            rows = len(self.__values)
            data = [[0]*rows]*columns
        
            for row in range(rows):
                for col in range(columns):
                    data[col][row] = self.__values[row][col]
            return data
Beim Programmstart erzeuge ich ein mein TableModel und weise das der Tabelle zu. Dazu übergebe ich ein paar Dummywerte damit was in der Tabelle drin steht. Diese werden korrekt ausgelesen!

Code: Alles auswählen

mlist = [[float(x) for y in range(2)] for x in range(self.ui.spinBox_nsx.value())]
        waveform_header = ['Time [ms]','Current [A]']
        self.waveformModel = TableModel(mlist, waveform_header)
        self.ui.TableWaveform.setModel(self.waveformModel)
Die Tabelle soll editierbar sein:

Code: Alles auswählen

    def flags(self, index):
        return QtCore.Qt.ItemIsEditable | QtCore.Qt.ItemIsEnabled | QtCore.Qt.ItemIsSelectable

Ich hoffe ich habe genug QuellCode gepostet damit ihr mein Problem versteht. Wenn nicht poste ich auch gerne mehr!

Grüße

Matthias
lunar

@Mosquitsch: Erkläre doch bitte, wo genau das Problem auftrittst, sprich, an welcher Stelle Du fehlerhafte oder unerwartete Werte erhältst, und was Du stattdessen erwartest. Das alles geht aus Deiner Problembeschreibung überhaupt nicht hervor, ".flags()" beispielsweise ist trivial, hat überhaupts nichts mit QVariant zu tun und ist daher wohl vollkommen irrelevant. Ich kann daher nur raten, und ich rate einfach mal, dass Dir an irgendeiner Stelle ein "value.toPyObject()" fehlt, um QVariant in Python-Typen umzuwandeln.

Zeige also bitte nicht noch mehr Quelltext, sondern den tatsächlich relevanten. Und am besten als minimales Beispiel, damit wir den Quelltext auch verstehend und selbst ausprobieren können.

Doppelte Unterstriche sind im Übrigen selten nötig, per Konvention werden private Attribute durch einfache Unterstriche markiert.
Mosquitsch
User
Beiträge: 8
Registriert: Donnerstag 3. November 2011, 09:50

Danke lunar, das hat geholfen.

Das Problem lag in meiner Funktion setData()

Code: Alles auswählen

    def setData(self, index, value, role = QtCore.Qt.EditRole):
        if role == QtCore.Qt.EditRole:
            
            row = index.row()
            column = index.column()          
            self.__values[row][column] = value.toPyObject()
            self.dataChanged.emit(index, index)
            return True
        return False
Mit .toPyObject() wird der richtige Wert angezeigt!

Ich hab erst mit PyQt angefangen. Das ist im Moment noch etwas verworren.
BlackJack

@Mosquitsch: Du hast da noch ein Problem das nichts mit Qt zu tun, sondern mit Python-Grundlagen. Der ``[obj] * n`` erzeugt eine Liste mit `n` *Referenzen* auf `obj` und *nicht* `n` Kopien von `obj`. Du hast also in `data` nicht `columns` verschiedene Listen, sondern `columns` mal die *selbe* Liste:

Code: Alles auswählen

In [236]: data = [[0] * 3] * 4

In [237]: data
Out[237]: [[0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0]]

In [238]: data[0] is data[1]
Out[238]: True

In [239]: data[0][0] = 42

In [240]: data
Out[240]: [[42, 0, 0], [42, 0, 0], [42, 0, 0], [42, 0, 0]]
Dieses erstellen einer "leeren" 2D-Liste um die dann in einer Schleife über Indexzugriffe mit Daten zu füllen ist IMHO aber sowieso etwas „unpythonisch“. Man würde eher die Liste durch erweitern erstellen. Also `append()` und/oder „list comprehensions“. Das mit den doppelten Unterstrichen hat lunar ja schon gesagt.
lunar

@Mosquitsch: Du siehst, dass der Fehler in einem Quelltextstück war, dass Du überhaupt nicht gezeigt hast. Zeige in Zukunft also bitte minimale lauffähige Beispiele, mit denen jeder andere den Fehler reproduzieren kann. So kann Dir viel schneller geholfen werden. :)
Mosquitsch
User
Beiträge: 8
Registriert: Donnerstag 3. November 2011, 09:50

@ luna Hab ich bemerkt.

Wollte nur nicht alles zuspammen. Wusste ja nicht wo der fehler liegt!

@ BlackJack

Ja, da sitze ich gerade dran. Hab bisher immer mit append() gearbeitet. Fand das aber nicht so schick. Das muss ich jetzt beheben!



Danke!
Mosquitsch
User
Beiträge: 8
Registriert: Donnerstag 3. November 2011, 09:50

Hallo,
nochmal ein kleiner nachtrag (möchte nicht extra ein neuen Thread aufmachen)

Wie kann ich in meinem TableModel die anzahl der Nachkommastellen einstellen? Z.Z. kann man nur 2 Stellen editieren, ich brauche aber vier.


Grüße

Matthias
lunar

@Mosquitsch: Ganz offensichtlich, indem Du in ".data()" eine Zeichenkette zurückgibst, welche die Zahl mit der entsprechenden Anzahl der Nachkommastellen enthält…

Die Alternative wäre ein eigener Delegate mit entsprechender "displayText()"-Implementierung.

Zum Schluss: Neue Frage, neuer Thread, insbesondere, wenn die neue Frage mit der alten eigentlich nichts mehr zu tun hat. Das macht die Sache einfacher, sowohl für diejenigen, die Dir helfen, also auch für andere, die dasselbe Problem haben. Danke :)
Mosquitsch
User
Beiträge: 8
Registriert: Donnerstag 3. November 2011, 09:50

Danke für die schnelle Antwort, aber das raffe ich irgendwie nicht!

Hier meine data() implementierung:

Code: Alles auswählen

    def data(self, index, role):
        
        
        if role == QtCore.Qt.EditRole:
            row = index.row()
            column = index.column()
            return self.__values[row][column]

              
        if role == QtCore.Qt.DisplayRole:
            
            row = index.row()
            column = index.column()
            value = self.__values[row][column]
            
            return value
lunar

@Mosquitsch: Bei allem Respekt, wenn Du daran scheiterst, Fließkommazahlen in Zeichenketten zu konvertieren, dann lerne lieber erst einmal die Grundlagen, bevor Du Dich weiterhin an Qt versuchst.

Wie dem auch sei, hier die Komplettlösung:

Code: Alles auswählen

def data(self, index, role):
    # …
    if role == QtCore.Qt.DisplayRole:
        value = self.values[index.row()][index.column()]
        return '{0:.4}'.format(value) if isinstance(value, float) else value
Mosquitsch
User
Beiträge: 8
Registriert: Donnerstag 3. November 2011, 09:50

Danke luna für die Hilfe.

Ich hab immer nach sowas wie setRealPrecision gesucht. Wenn ich eine Real zahl haben will ist es nicht das naheliegenste das in einen string zu konvertieren.
lunar

@Mosquitsch: Hast Du meine vorletzte Antwort nicht gelesen? Was gab es daran nicht zu „raffen“?!
Mosquitsch
User
Beiträge: 8
Registriert: Donnerstag 3. November 2011, 09:50

Tschuldige, ich verstehe dein Problem ist. Jeder hat mal ne lange Leitung.

Mal absehen davon funktioniert dein Code so nicht.
Es muss

Code: Alles auswählen

'{0:.7}'.format(value)
heißen.

Trotzdem danke für dein Hilfe.
lunar

@Mosquitsch: Du hast von vier Nachkommastellen gesprochen, und zeigst nun Quelltext, der sieben darstellt?!
Mosquitsch
User
Beiträge: 8
Registriert: Donnerstag 3. November 2011, 09:50

Er zeigt mit {0:.7} vier Nachkommastellen an! Anscheinend ist die Notation so, dass zwei Stellen vor dem Komma, das Komma selbst und die NSK gezählt werden.
lunar

@Mosquitsch: Stimmt, mein Fehler. Es muss "'{0:.4f}.format(value)" heißen, um die Darstellung mit einer festen Anzahl von Nachkommastellen zu erzwingen. Ohne "f" wird bei der Darstellung auf vier signifikante Stellen gerundet.
Antworten