Qt Checkbox If-Anweisung

Python und das Qt-Toolkit, erstellen von GUIs mittels des Qt-Designers.
Antworten
Ligurio
User
Beiträge: 22
Registriert: Montag 23. November 2015, 11:00

Hallo ihr fleißigen Programmierer,
Ich habe seid gestern mit Pyhton angefangen und stehe bei der If-Anweisung auf dem Schlauch. Selber habe ich schon sehr viel mit VBA zu tun gehabt jedoch habe ich keine If-Anweisung mit einer Checkbox hinbekommen. Python ist doch etwas anders :D

was ich erreichen möchte:
Wenn die Checkbox (in Qt Designer "checkBox" benannt) "checked" ist also mit haken drinne, soll einfach was passieren
z.B
if ..... :
w.Textfeld.setText("Haken drinne")

außerdem würde ich gerne abfragen z.B. wenn Textfeld leer (denke mal mit "") im Code dann mach irgendwas (auch mit einer If anweisung)
Wäre super wenn mir wer helfen könnte. habe nichts im Netz gefunden was geklappt hat. Ich denke sollte gar net ma so schwer sein. :K


Vielen Dank schonmal.
Gruß
Ligurio

Dies ist mal Code für meine Übungsdatei was ich alles schon hinbekommen habe mit einer GUI :

Code: Alles auswählen

import sys
from PyQt4.QtCore import *     
from PyQt4.QtGui import *      
from PyQt4.uic import *       

def buttonKlick():       
    sys.exit()           
def buttonKlick2():
    w.Textfeld.setText("Es wurde geklickt")

def checkboxFunktion():
    w.checkBox.setChecked(True)
def checkboxFunktion2():
    w.checkBox.setChecked(False)

app = QApplication(sys.argv)    
w = loadUi("Fenster.ui")        

w.connect(w.BeendenKnopf, SIGNAL("clicked()"),buttonKlick) 
w.connect(w.Klicken, SIGNAL("clicked()"),buttonKlick2) 
w.connect(w.Datei1, SIGNAL("triggered()"),checkboxFunktion)
w.connect(w.Datei2, SIGNAL("triggered()"),checkboxFunktion2)

#schreibt ins Textfeld
w.Textfeld.setText("test")   
    
w.show()                        
app.exec_()                     
sys.exit()
Zuletzt geändert von Anonymous am Montag 23. November 2015, 11:38, insgesamt 1-mal geändert.
Grund: Quelltext in Python-Codebox-Tags gesetzt.
BlackJack

@Ligurio: Für die Checkbox brauchst Du kein ``if``, da musst Du nur das entsprechende Signal mit einer Funktion oder Methode verbinden. Welches das ist verrate ich jetzt mal nicht, denn das steht laut und deutlich in der Qt-Dokumentation.

Apropos Dokumentation: In der Python-Dokumentation gibt es ein Python-Grundlagentutorial. Das, oder etwas vergleichbares, solltest Du mal durchgerarbeitet haben, inklusive objektorientierter Programmierung (OOP), denn das braucht man für GUI-Programmierung.

Sonstiges zum Quelltext: Sternchen-Importe sind Böse™. Man weiss am Ende nicht welcher Name aus welchem Modul kommt, es werden gerade bei GUI-Rahmenwerken Unmengen an Namen importiert die gar nicht verwendet werden, und es kann zu Namenskollisionen kommen.

Auf Modulebene sollten nur Definitionen von Konstanten, Funktionen, und Klassen stehen. Das Hauptprogramm steht üblicherweise in einer Funktion die `main()` heisst und durch folgendes Idiom gestartet wird, damit man das Modul nicht nur direkt ausführen kann, sondern auch importieren kann ohne dass das Hauptprogramm gleich losläuft:

Code: Alles auswählen

if __name__ == '__main__':
    main()
`sys.exit()` sollte man nicht irgendwo im Programm machen weil das den gesamten Prozess beendet ohne das vielleicht andere Programmteile noch die Chance haben Aufräumarbeiten zu erledigen. GUI-Programme beendet man dadurch das man die GUI-Hauptschleife beendet und der Programmfluss danach ganz normal zum Ende kommt. Bei Qt hat man ausserdem die Möglichkeit die Anwendung enden zu lassen in dem man alle Fenster schliesst.

Namen sollte man nicht abkürzen solange die Abkürzung nicht allgemein bekannt ist oder der Gültigkeitsbereich nicht sehr stark eingeschränkt ist. `w` für einen programmweiten Namen ist nicht gut.

Zum Verbinden von Signalen und Slots gibt es schon etwas länger einen kürzeren und auch etwas sichereren Weg:

Code: Alles auswählen

w.connect(w.BeendenKnopf, SIGNAL("clicked()"),buttonKlick)

# ->

w.BeendenKnopf.clicked.connect(buttonKlick)
Am ”natürlichen” Programmende braucht man kein `sys.exit()`, das passiert automatisch.
Ligurio
User
Beiträge: 22
Registriert: Montag 23. November 2015, 11:00

Vielen Dank BlackJack für deine ausführliche Antwort.
Ich habe mir schon gedacht das mein Code hier nicht ganz ordentlich ist ;) habe ich mir nur aus bruchstücken zusammengebastelt und schonmal gefreut das es grob funktioniert hat.

Qt-Dokumentation werde ich natürlich gleich mal lesen.

das mit den "Sternchen-Import" habe ich leider noch nicht ganz verstanden. wie sollte ich es denn umschreiben damit meine .ui Datei mit geladen wird?

Das Verbinden mit den Signalen ist mit deiner Variante echt viel schöner :D danke für die info. kennst du zufällig eine Seite wo ich sehen kann welche befehle welcher Knopf/checkbox usw ausführen kann ("clicked")
BlackJack

@Ligurio: Statt mit Sternchen alles aus einem Modul zu importieren importiert man entweder nur das Modul und greift dann über das Modul auf die Namen darin zu, oder man importiert direkt nur die Namen aus dem Modul die man benötigt. Das entscheidet sich oft daran wieviele Namen man aus einem Modul benötigt oder wie eindeutig die Namen sind. Wenn sie zu generisch sind, kann der Modulname Kontext liefern und das Programm lesbarer machen. Bezüglich der *.ui-Datei kann man beispielsweise ``from PyQt4.uic import loadUi`` schreiben und dann die ``loadui('dateiame.ui')`` schreiben, oder ``from PyQt4 import uic`` und dann ``uic.loadUi('dateiname.ui')``.

Das was Du Befehle nennst heisst bei Qt Signale und welche Signale ein von `QObject` abgeleitetes Objekt senden kann steht in der Qt-Dokumentation. Dort gibt es auch ein Kapitel welches das Signal & Slots-Konzept allgemein einführt. Insgesamt ist die Qt-Dokumentation recht gut und umfangreich, insbesondere auch was Konzepte angeht statt nur die API verteilt über alle Datentypen zu beschreiben.
Ligurio
User
Beiträge: 22
Registriert: Montag 23. November 2015, 11:00

Ich seh schon ich bin bei dir richtig gut aufgehoben. ;)
Vielen Dank für deine Hilfe. werde ich aujedenfall umbauen, damit ich keine * mehr habe

Du sprichst immer von "DER" Qt-Dokumentation. ich glaube aber ich habe über google nicht deine gefunden. könntest du mir vll einen Link zukommen lassen? wäre super lieb. dann habe ich eine schöne Hilfe und kann bissl experimentieren. Wenn ich dann spezielle Fragen habe melde ich mich wieder

Python GUI schein mir bissl komplizierter zu sein als VBA-Userform :D
Wollte mir zu Weihnachten ein Raspberry Pi kaufen und dachte mir übe schonmal weng mit Pyhton. :roll: :mrgreen:
BlackJack

Die Qt-Dokumentation findet man auf der Qt-Website: http://doc.qt.io/qt-4.8/
BlackJack

Ungetestet und immer noch mit teilweise nicht so schönen Namen für die Widgets in der UI-Datei:

Code: Alles auswählen

import sys
from functools import partial
from PyQt4.QtGui import QApplication   
from PyQt4.uic import loadUi
 

class Window(object):

    def __init__(self):
        self.ui = loadUi('Fenster.ui')
        self.ui.BeendenKnopf.clicked.connect(self.ui.quit)
        self.ui.Klicken.clicked.connect(self.on_button)
        self.ui.Datei1.triggered.connect(partial(self.ui.checkBox.setChecked, True))
        self.ui.Datei2.triggered.connect(partial(self.ui.checkBox.setChecked, False))
        self.ui.Textfeld.setText('test')
        self.ui.show()

    def on_button(self):
        self.ui.Textfeld.setText('Es wurde geklickt')


def main():
    app = QApplication(sys.argv)    
    window = Window()
    app.exec_()                    


if __name__ == '__main__':
    main()
Ligurio
User
Beiträge: 22
Registriert: Montag 23. November 2015, 11:00

Oh echt super nett dass du mir es umgeschrieben hast. ich war gerade auch dabei. Habe auch meine Knöpfe usw jetzt verständlich umbenannt. Ich verstehe sogar jetzt deinen ganzen Code 8)
Wenn ich deinen Code laufen lasse (die Buttons jetzt natürlich an die .ui angepasst) kommt ein komischer Fehler:
runfile(' hier steht mein Pfad mit .py', wdir=' nochmal mein Pfad ohne .py')

in der Dokumentation stehen alle befehle die ich verwenden könnte. aber ich bekomme es immer noch nicht hin wenn checkBox True (haken drinne) etwas passiert und wenn haken draußen etwas anderes.
habe zum test mal mit clicked geschrieben. Könntest du mir verraten mit was ich "clicked" ersetzten muss?

Code: Alles auswählen

def LabelFunktion1():
    Fenster.Label.setText("Haken drinnen")
def LabelFunktion2():
    Fenster.Label.setText("Haken draußen")

Fenster.checkBox.clicked.connect(LabelFunktion1)
schonmal 1000 Dank für deine Hilfe.
Es ist nicht immer selbstverständlich dass fremde leute einem so ausführlich helfen und ihr zeit dafür opfern. :oops: :)
Benutzeravatar
cofi
Python-Forum Veteran
Beiträge: 4432
Registriert: Sonntag 30. März 2008, 04:16
Wohnort: RGFybXN0YWR0

Dein Ansatz funktioniert nicht. Das "clicked" Event wird ausgeloest, wenn die Checkbox geklickt wird, nicht nur wenn der Haken gesetzt wird.
Sprich: Du brauchst eine Funktion fuer das Event, die sich anschaut wie der Status der Checkbox ist und dann die entsprechenden Aktionen ausfuehrt.

Da ich gerade sehe, dass du wieder von BlackJacks Klassenvorschlag weg gehst: Tu das nicht. Eine nicht-klassenbasierte GUI benutzt zwangslaeufig globale Variablen was sie schlecht verstaendlich und schwer nachvollziehbar macht.

Fuer die Zukunft, bitte setze deinen Code in die entsprechende Codebox mit der Listbox ueber dem Textfeld.
Ligurio
User
Beiträge: 22
Registriert: Montag 23. November 2015, 11:00

Ja die Variante von BlackJack werde ich weiter verwenden. hatte nur das Beispiel auf der alten Variante geschrieben um mein Problem klar zu machen.

Aber ich komme einfach nicht auf diese kleine codezeile die den Status abfragen tut und ich dann mit dieser Variable meine 2 aktionen ausführen kann

Code: Alles auswählen

Test = Fenster.checkBox.isChecked()
if Test == True:
    Fenster.Label.setText("Haken drinnen")
else:
    Fenster.Label.setText("Haken draußen")
Hiermit schaffe ich nur eine Abfrage wenn ich in der .ui den Haken schon setzte bzw rausnehme wirds angezeigzt
Zuletzt geändert von Ligurio am Montag 23. November 2015, 18:22, insgesamt 1-mal geändert.
Benutzeravatar
cofi
Python-Forum Veteran
Beiträge: 4432
Registriert: Sonntag 30. März 2008, 04:16
Wohnort: RGFybXN0YWR0

Die `isChecked` Methode ist der Schluessel. Fuer BlackJacks Code:

Code: Alles auswählen

def on_button(self):
    self.ui.Textfeld.setText('Haken %s' % ('gesetzt' if self.ui.Klicken.isChecked() else 'entfernt'))
Ligurio
User
Beiträge: 22
Registriert: Montag 23. November 2015, 11:00

Danke dir für die Hilfe. an diese Methode hatte ich auch gedacht.

Jetzt würde ich nur noch gerne wissen an was das liegen könnte das ich den "schönen" Code von BlackJack mit copy - paste nicht zum laufen bekomme. Die einrückungen passen weiterhin alle
Ligurio
User
Beiträge: 22
Registriert: Montag 23. November 2015, 11:00

Ah Fehler gefunden lag an dieser Zeile:

Code: Alles auswählen

self.ui.BeendenKnopf.clicked.connect(self.ui.quit)
habe sie einfach auskommentiert dann läufts. Danke euch beiden
Ligurio
User
Beiträge: 22
Registriert: Montag 23. November 2015, 11:00

Nach langem Probieren funktioniert es immer noch nicht perfekt das was ich im 1. Post wollte:
wenn Checkbox Haken drinn = mach was
wenn Checkbox Haken draußen = mach was (z.B. Textfeld was reinschreiben)

mit euren Hilfe Codes Funktioniert Grundgerüst super und mit dem vorgeschlagenem von Cofi wird die Checkbox zwar abgefragt aber mit einem Klick auf einen Button :P
Habe jetzt schon lange rumgebastelt, aber bekomme es nicht hin das wenn die Checkbox angeklickt wird sofort etwas passiert und wenn haken raus wieder etwas.

Muss ich hierfür das Fenster immer neu aktualisieren? wenn vor dem erstellen des Fensters der Haken gesetzt/nicht gesetzt wird (in der .ui bearbeitet) so funktioniert es nur einmal beim starten

Code: Alles auswählen

self.ui.Textfeld.setText('Haken %s' % ('gesetzt' if self.ui.checkBox.isChecked() else 'entfernt'))
BlackJack

@Ligurio: Man muss halt das richtige Signal von der Checkbox verbinden. Ich verweise da nochmal auf die Dokumentation. Einfach mal die Beschreibung von `QCheckbox` durchlesen.
Ligurio
User
Beiträge: 22
Registriert: Montag 23. November 2015, 11:00

Heureka !!!!
Hab es gepackt. jetzt nur noch 2 kleine Fragen:
geht das hier "kürzer" bzw intelligenter:

Code: Alles auswählen

class Window(object):
    def __init__(self):
        self.ui = loadUi('Fenster.ui')
#self.ui.BeendenKnopf.clicked.connect(self.ui.quit)
        self.ui.checkBox.clicked.connect(self.Test)
    def Test(self):
        self.ui.Textfeld.setText('Haken %s' % ('gesetzt' if self.ui.checkBox.isChecked() else 'entfernt'))
und warum funktioniert der [...] (self.ui.quit) nicht?

habe durch euch mein Tagesziel gerade noch erreicht ;)
Antworten