Formularfeld Typ feststellen

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
django122
User
Beiträge: 2
Registriert: Donnerstag 20. Februar 2020, 11:31

Hallo,

ich habe lange mit mir gehadert, ob ich mein Problem hier einstellen soll oder nicht. Aber jetzt will ich es doch tun, da meine Suche mit Google und Co. keinen Erfolg brachte.

Folgende Umgebung, mit Qt Designer erstellt und ins Programm eingebunden:
Ein Formular mit ca. 30 LineEdit (Text) Feldern, ein paar Checkbox und einem TableWidget.
Das Formular füttert mit seinen Eingabeobjekten dieses Tablewidget, welches wiederum eine Datenbank füllt und eine Art Adressdatenbank darstellt.

Das Anzeigen der Daten aus der Datenbank in das Tablewidget und Abspeichern von neuen Datensätzen aus dem Formular funktioniert bereits.
Wenn ich aber durch "Doppelklick" auf eine Zeile im Widget die Daten in das Formular übernehmen will, bleibt das Programm spätestens an der ersten ComboBox stehen.
Die ComboBox unterstützt nicht das Attribut .setText() Soweit klar.
Wie kann ich den Typ des Feldes herausfinden um damit das richtige Attribut zu nehmen?
Ich fülle im Moment die Felder des Formulars mit Hilfe eines Arrays, in dem alle Feldnamen stehen.

In meiner Unwissenheit könnte ich mir sowas vorstellen wie: Ist es eine ComboBox, dann rufe def combobox auf, ermittle den aktuellen Index vom einzutragenden Wert und zeige ihn an.
Ähnliches würde ich dann mit den Checkboxen machen.
Gibt es so einen Befehl der mit im Klartext sagt, es handelt sich hier um eine Combobox, eine Checkbox, ein Lineedit?

Für eine kleine Hilfestellung wäre ich dankbar. Mein Wissensstand zu Python würde ich mit "geht schon" bezeichnen. Wenn's geht bitte einfach.
Danke
Matthias
__deets__
User
Beiträge: 14545
Registriert: Mittwoch 14. Oktober 2015, 14:29

Es gibt verschiedene Ansaetze. Zum einen gibt es die Moeglichkeit, den Typ eines Objektes mit isinstance rauszufinden, und basierend darauf zu verzweigen. Das funktioniert fuer den von dir soweit geschilderten Fall, aber setzt dann voraus, dass wirklich immer fuer jede ComboBox etc das genau gleiche passieren muss. Alternativ kann man sich zB ein dictionary bauen, das Feldnamen auf Hilfsfunktionen abbildet, die dann immer das passende machen. Und den Vorteil haben, zB eine kryptische Abkuerzung in einem Feld der Datenbank in etwas lesbares zu uebersetzen, bevor das dann tatsaechlich dargestellt wird. Mal eine Skizze, die ein paar Annahmen trifft:

- der Datensatz liegt als dictionary vor (also zB { feld: wert, ...} aus der Datenbankabfrage/der Tabellenzeile)
- per Namen sind die Controls des Feldes auffindbar.

Code: Alles auswählen


def convert_drivers_license(control, value):
    real_value = something_with_value(value)
    control.setCurrentText(real_value)

CONVERTERS = {
    "title": QComboBox. setCurrentText,
    "drivers_license": convert_drivers_license,
}

def setDataFromEntry(self, entry):
     for name, value in entry.items():
         converter = CONVERTERS.get(name, QLineEdit.setText)  # default annahme: es ist ein LineEdit
         converter(self.ui.findObject(name), value)
django122
User
Beiträge: 2
Registriert: Donnerstag 20. Februar 2020, 11:31

Danke für dein Beispiel.

So lange es sich um ein QLineEdit Feld handelt, ist alles ok. Auch den richtigen Wert in die ComboBox zu bekommen, ist gelöst. Ich mache es so:

Code: Alles auswählen

    def setzeCombo(self):
        Feld = ["Zustand"]  # Array mit Feldnamen
        preset = "self."    
        inhalt = "schlecht"  # Daten aus dem TableWidget
        befehl = preset + Feld[0] + ".findText('" + inhalt + "')"
        print('a = ' + befehl)  # nur zur Kontrolle
        a = eval(befehl)
        print (a)  # Index in der Combobox
        self.Zustand.setCurrentIndex(a)  #damit geht's 
Aber zu unterscheiden ob es sich um ein QLineEdit oder QComboBox Feld handelt, ist in deinem Beispiel nicht aufgeführt. Oder täusche ich mich da?
Die Idee mit dem Dictionary ist gut. Ich denke, damit klappt es.
Danke
Sirius3
User
Beiträge: 18272
Registriert: Sonntag 21. Oktober 2012, 17:20

Strings setzt man nicht mit + zusammen, sondern benutzt Stringformatierung. Der Inhalt von inhalt muß auch entsprechend behandelt werden, dass er keine Sonderzeichen enthält:

Code: Alles auswählen

befehl = f"self.{Feld[0]}.findText({inhalt!r})"
ABER: `eval` sollte man nicht benutzen. Hier kann man einfach `getattr` benutzen:

Code: Alles auswählen

    def setzeCombo(self):
        Feld = ["Zustand"]  # Array mit Feldnamen
        inhalt = "schlecht"  # Daten aus dem TableWidget
        a = getattr(self, Feld[0]).findText(inhalt)
        print (a)  # Index in der Combobox
        self.Zustand.setCurrentIndex(a)
__deets__
User
Beiträge: 14545
Registriert: Mittwoch 14. Oktober 2015, 14:29

@django122: doch, mein Beispiel unterscheidet zwischen LineEdit und ComboBox - du musst nochmal genau hinschauen. Ich mache das allerdings NICHT via des Typs, eben weil ich die Moeglichkeit fuer spezifische Behandlung freihalten will. Die ich ja auch zeige.

Und Sirius3 hat's schon erwaehnt, aber ich betone das nochmal: vergiss, dass es eval (und den grossen Bruder exec) gibt. Die sind klar auf der dunklen Seite der Macht, und man muss viel wissen, bis man an einen Punkt kommt, wo man sie sicher handhaben kann.
Antworten