merkwürdiges Verhalten QIntValidator

Python und das Qt-Toolkit, erstellen von GUIs mittels des Qt-Designers.
Benutzeravatar
noisefloor
User
Beiträge: 1735
Registriert: Mittwoch 17. Oktober 2007, 21:40
Wohnort: Görgeshausen
Kontaktdaten:

merkwürdiges Verhalten QIntValidator

Beitragvon noisefloor » Dienstag 17. Januar 2012, 19:49

Hallo,

folgendes Prog funktioniert, aber der Validator verhält sich IMHO komisch:

Code: Alles auswählen

#!/usr/bin/env python
# ~*~ coding: utf-8 ~*~

import sys

from PySide import QtGui

class SimpelQt(QtGui.QDialog):
    def __init__(self,parent=None):
        super(SimpelQt, self).__init__(parent)
        self.setWindowTitle('Simpel Qt')
        layout = QtGui.QVBoxLayout()
        self.eingabe = QtGui.QLineEdit()
        self.eingabe_valid = QtGui.QIntValidator(0,1000,self)
        self.eingabe.setValidator(self.eingabe_valid)
        layout.addWidget(self.eingabe)
        self.button = QtGui.QPushButton(u'Quadrieren')
        layout.addWidget(self.button)
        self.label = QtGui.QLabel(u'Ergebnis...')
        layout.addWidget(self.label)
        self.setLayout(layout)
        self.button.clicked.connect(self.rechnen)

    def rechnen(self):
        wert = int(self.eingabe.text())
        return self.label.setText(unicode(wert*wert))

if __name__ == '__main__':
    app = QtGui.QApplication(sys.argv)
    simpel_qt = SimpelQt()
    simpel_qt.show()
    sys.exit(app.exec_())


Gibt man z.B. "1.1" oder "1,1" erhält man als Ergebnis 121, weil der Punkt bzw. das Komma einfach "verschwinden"...

Bug oder Feature? Wenn Feature - was ist dann der Sinn des _Int_-Validators?

Pyside + Qt4 Version ist die aus den Ubuntu Oneiric Quellen.

Gruß, noisefloor
Zuletzt geändert von noisefloor am Sonntag 22. Januar 2012, 19:49, insgesamt 1-mal geändert.
Benutzeravatar
BlackJack
Moderator
Beiträge: 32975
Registriert: Dienstag 25. Januar 2005, 23:29
Wohnort: Berlin
Kontaktdaten:

Re: merkwürdiges Verhaltn QIntValidator

Beitragvon BlackJack » Dienstag 17. Januar 2012, 19:54

@noisefloor: Wie gibst Du denn "1.1" ein? Den '.' oder das ',' kannst Du doch gar nicht eingeben? Und genau das ist der Sinn von dem Validator — der Inhalt muss zu *jeder* Zeit einem `int` im Wertebereich entsprechen. Etwas anderes wird gar nicht erst zugelassen.
“Programs must be written for people to read, and only incidentally for machines to execute.” — Abelson & Sussman, SICP (preface to the first edition)
Benutzeravatar
noisefloor
User
Beiträge: 1735
Registriert: Mittwoch 17. Oktober 2007, 21:40
Wohnort: Görgeshausen
Kontaktdaten:

Re: merkwürdiges Verhaltn QIntValidator

Beitragvon noisefloor » Dienstag 17. Januar 2012, 20:29

Hallo,

Etwas anderes wird gar nicht erst zugelassen.


Das dachte ich auch. Aber es wird genommen... Ganz regulär über die Tastatur :?:

Buchstaben werden in der Tat ignoriert.

Kann das jemand bei sich nachvollziehen mit dem obigen Programm?

Gruß, noisefloor
Benutzeravatar
BlackJack
Moderator
Beiträge: 32975
Registriert: Dienstag 25. Januar 2005, 23:29
Wohnort: Berlin
Kontaktdaten:

Re: merkwürdiges Verhaltn QIntValidator

Beitragvon BlackJack » Dienstag 17. Januar 2012, 21:18

@noisefloor: Also ich kann es nicht nachvollziehen. Ich kann nur Ziffern eingeben.
“Programs must be written for people to read, and only incidentally for machines to execute.” — Abelson & Sussman, SICP (preface to the first edition)
Benutzeravatar
noisefloor
User
Beiträge: 1735
Registriert: Mittwoch 17. Oktober 2007, 21:40
Wohnort: Görgeshausen
Kontaktdaten:

Re: merkwürdiges Verhaltn QIntValidator

Beitragvon noisefloor » Mittwoch 18. Januar 2012, 08:51

Hallo,

strange... Ich kann als _erste_ Eingabe auch keinen Punkt oder Komma machen. Wenn ich zuerst aber eine Zahl eingebe, dann nimmt er . und , ...

Muss das morgen mal unter Windows testen...

Gruß, noisefloor
JonasR
User
Beiträge: 251
Registriert: Mittwoch 12. Mai 2010, 13:59

Re: merkwürdiges Verhaltn QIntValidator

Beitragvon JonasR » Mittwoch 18. Januar 2012, 11:59

Unter Windows habe ich das Gleiche. Erste Ziffer muss eine Zahl sein danach kann man einen Punkt oder ein Komma machen. Bei absenden wird aber beides raus genommen.

€ Nach jeder Zahl kann man ein Punkt oder Komma machen.
Benutzeravatar
Hyperion
Moderator
Beiträge: 7471
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

Re: merkwürdiges Verhaltn QIntValidator

Beitragvon Hyperion » Mittwoch 18. Januar 2012, 12:39

Ich hab 's unter Unbuntu (Oneiric) getestet und komme ebenfalls zu dem Ergebnis, dass man entweder Punkte oder Kommata eingeben kann - lustiger Weise nicht beides in einem String!

Man kann das auch ohne GUI drum herum testen:

Code: Alles auswählen

In [19]: from PySide import QtGui

In [20]: v = QtGui.QIntValidator(0, 100, None)

In [21]: v.validate("5.6", 0)
Out[21]: (PySide.QtGui.QValidator.State.Intermediate, u'5.6', 0)

In [22]: v.validate("5,6", 0)
Out[22]: (PySide.QtGui.QValidator.State.Intermediate, u'5,6', 0)

In [23]: v.validate("5,.", 0)
Out[23]: (PySide.QtGui.QValidator.State.Invalid, u'5,.', 0)


Ich vermute mal, dass das irgend wie am `locale` liegt...

Ich würde als parent vom Validator übrigens `self.eingabe`, also das zugehörige QLineEdit, wählen. Ändert natürlich nichts am Problem ;-)
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3))
assert encoding_kapiert
Benutzeravatar
BlackJack
Moderator
Beiträge: 32975
Registriert: Dienstag 25. Januar 2005, 23:29
Wohnort: Berlin
Kontaktdaten:

Re: merkwürdiges Verhaltn QIntValidator

Beitragvon BlackJack » Mittwoch 18. Januar 2012, 12:59

Bei mir sieht das so aus:

Code: Alles auswählen

In [147]: v.validate("5.6", 0)
Out[147]: (PySide.QtGui.QValidator.State.Invalid, u'5.6', 0)


Aber „locale” scheint eine vernünftige Vermutung, wenn man zum Beispiel in einer angelsächsischen „locale” '50.0' oder "1,000,000" als Schreibweisen für ganze Zahlen zulassen würde. Dann müsste auch '.' und ',' in einer Zahl gehen: "4,711.23". Für eine deutsche „locale” müsste man dann die beiden Trennzeichen vertauschen.
“Programs must be written for people to read, and only incidentally for machines to execute.” — Abelson & Sussman, SICP (preface to the first edition)
Benutzeravatar
Hyperion
Moderator
Beiträge: 7471
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

Re: merkwürdiges Verhaltn QIntValidator

Beitragvon Hyperion » Mittwoch 18. Januar 2012, 13:08

Also bei mir klappt das aber so auch nicht:

Code: Alles auswählen

In [61]: from PySide import QtCore

In [62]: loc = QtCore.QLocale()

In [63]: loc.groupSeparator()
Out[63]: u'.'

In [64]: loc.toInt("12")
Out[64]: (12, True)

In [65]: loc.toInt("1.2")
Out[65]: (0, False)

In [66]: loc.numberOptions()
Out[66]: 0

Genau das Verhalten würde ich erwarten - aber der `QIntValidator` verhält sich da ja anders :-(

Auch das Einstellen mittels `setNumberOptions` funzt nicht :-(

Code: Alles auswählen

In [67]: loc.setNumberOptions(QtCore.QLocale.OmitGroupSeparator)

In [68]: loc.toInt("1.2")
Out[68]: (0, False)

In [69]: loc.numberOptions()
Out[69]: 1

In [70]: loc.setNumberOptions(QtCore.QLocale.RejectGroupSeparator)

In [71]: loc.toInt("1.2")
Out[71]: (0, False)

In [72]: loc.numberOptions()
Out[72]: 2

Das wäre jetzt eine Erklärung gewesen, wie der Validator evtl. vorgehen könnte... ist aber leider auch nicht so.
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3))
assert encoding_kapiert
Benutzeravatar
BlackJack
Moderator
Beiträge: 32975
Registriert: Dienstag 25. Januar 2005, 23:29
Wohnort: Berlin
Kontaktdaten:

Re: merkwürdiges Verhaltn QIntValidator

Beitragvon BlackJack » Mittwoch 18. Januar 2012, 14:05

@Hyperion: Was wolltest Du damit jetzt zeigen? Wenn man den „group separator” an einer ungültigen Stelle setzt, dann ist das natürlich auch eine ungültige Zahl. Setz ihn doch mal korrekt.

Code: Alles auswählen

In [155]: loc.groupSeparator()
Out[155]: u','

In [156]: loc.toInt("1,2")
Out[156]: (0, False)

In [157]: loc.toInt('1,200')
Out[157]: (1200, True)
“Programs must be written for people to read, and only incidentally for machines to execute.” — Abelson & Sussman, SICP (preface to the first edition)
Benutzeravatar
Hyperion
Moderator
Beiträge: 7471
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

Re: merkwürdiges Verhaltn QIntValidator

Beitragvon Hyperion » Mittwoch 18. Januar 2012, 14:10

*patsch* OMG... ja, manchmal hat man ein Brett vorm Kopf :-D

Code: Alles auswählen

In [83]: loc.toInt(u"1.200")
Out[83]: (1200, True)

In [84]: loc.setNumberOptions(QtCore.QLocale.RejectGroupSeparator)

In [85]: loc.toInt(u"1.200")
Out[85]: (0, False)

Ok, das passt dann ja. Damit wäre es wohl eine Lösung, die `NumberOptions` entsprechend zu setzen, wenn man keine Punkte oder Kommata akzeptiert haben will.
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3))
assert encoding_kapiert
JonasR
User
Beiträge: 251
Registriert: Mittwoch 12. Mai 2010, 13:59

Re: merkwürdiges Verhaltn QIntValidator

Beitragvon JonasR » Mittwoch 18. Januar 2012, 14:41

Ich kann bei mir auch Sachen wie 1,1,1, eingeben... natürlich das gleiche mit Punkten
Benutzeravatar
noisefloor
User
Beiträge: 1735
Registriert: Mittwoch 17. Oktober 2007, 21:40
Wohnort: Görgeshausen
Kontaktdaten:

Re: merkwürdiges Verhaltn QIntValidator

Beitragvon noisefloor » Mittwoch 18. Januar 2012, 20:14

Hallo,

bleibt aber die Frage: Ist das ein Bug, den man mal melden sollte?

Gruß, noisefloor
lunar

Re: merkwürdiges Verhaltn QIntValidator

Beitragvon lunar » Mittwoch 18. Januar 2012, 20:48

@Alle: Dieses Verhalten ist kein Fehler, sondern Feature, und im Übrigen auch dokumentiert. Nur hat hier offenbar niemand die Dokumentation gelesen. Der Sinn von "QIntValidator" ist nicht, einfach nur Ziffern als Eingabe zu akzeptieren. Das wäre trivial (siehe Ende dieses Beitrags). "QIntValidator" ermöglicht eine den Spracheinstellungen entsprechende Eingabe von Zahlen, und mithin auch Tausender-Trennzeichen.

Grundsätzlich kann man in "QIntValidator" dabei sowohl das den Spracheinstellungen entsprechende Eingabeformat nutzen also auch dasjenige der Standard-C-Lokalisierung:
[...] QIntValidator uses its locale() to interpret the number. For example, in Arabic locales, QIntValidator will accept Arabic digits. In addition, QIntValidator is always guaranteed to accept a number formatted according to the "C" locale.

Mithin kann man bei deutscher Spracheinstellung sowohl den Punkt als auch das Komma als Tausender-Trennzeichen nutzen, nicht aber beides gleichzeitig. Im ersten Fall parst Qt die Zeichenkette gemäß der deutschen Spracheinstellung, im letzteren Fall gemäß den Regeln der POSIX-Lokalisierung.

Fehlerhaft platzierte Tausender-Trennzeichen werden in "QIntValidator.fixup()" wieder entfernt, damit die Eingabe als Zahl geparst werden kann. Anders ließe sich eine Eingabe von Zahlen mit Tausender-Trennzeichen innerhalb der Möglichkeiten von "QValidator" gar nicht umsetzen, da man von vorne herein nie sicher sein kann, ob nun noch Ziffer nach dem Trennzeichen eingegeben werden oder nicht. Du kannst zwar von "QIntValidator" ableiten und ".fixup()" überschreiben, musst dann aber auch ".validate()" so verändern, dass "Invalid" zurückgegeben wird, wenn das Tausender-Trennzeichen an falscher Stelle steht. Das ist nicht trivial.

Zumal Dein Quelltext ohnehin fehlerhaft ist, da Du "int()" verwendest, um die validierte Eingabe zu parsen. "int()" ignoriert die Spracheinstellungen der Umgebung, die validierte Eingabe ist aber abhängig von der Lokalisierung. Wenn Du "QIntValidator" verwendest, musst Du die Eingabe mit "QLocale" parsen.

In Deinem Fall bist Du allerdings wohl besser bedient mit einem eigenen, ziemlich trivialen "QValidator":

Code: Alles auswählen

class StrictIntValidator(QValidator):
    def __init__(self, min, max, parent=None):
        QValidator.__init__(self, parent)
        self.min = min
        self.max = max

    def validate(self, input, pos):
        try:
            value = int(input.strip())
            state = QValidator.Acceptable if self.min <= value <= self.max else QValidator.Invalid
            return state, input, pos
        except ValueError:
            return QValidator.Invalid
Benutzeravatar
noisefloor
User
Beiträge: 1735
Registriert: Mittwoch 17. Oktober 2007, 21:40
Wohnort: Görgeshausen
Kontaktdaten:

Re: merkwürdiges Verhaltn QIntValidator

Beitragvon noisefloor » Mittwoch 18. Januar 2012, 21:05

Hallo,

@lunar: Ah, Danke für die Erklärung. Jetzt habe ich es auch verstanden. :-)

Wobei ich selber nie auf die Idee kommen würde, ein Zahl mit Tausender-Separatoren einzutippen - weder in Qt noch in Excel noch in ... aber egal, anderes Thema.

Gruß, noiselfoor

Zurück zu „Qt/KDE“

Wer ist online?

Mitglieder in diesem Forum: 0 Mitglieder