Radiobuttonwert außerhalb der Klasse verwenden

Fragen zu Tkinter.
Antworten
Soxxes
User
Beiträge: 12
Registriert: Mittwoch 28. August 2019, 14:53

Hallo zusammen,

mein Ziel ist es, ein Auswahlfenster mit drei Optionen zu erstellen, von denen eine Option auszuwählen ist und deren Wert an das nachfolgende Programm weitergegeben werden soll. Das Programmverhalten soll abhängig von der Auswahl sein.
Ich bin noch recht unerfahren mit Tkinter, habe aber schon gelesen, dass es "Best Practice" sei, das Ganze mit Objektorientierung umzusetzen.

Code: Alles auswählen

import tkinter as tk


class AuswahlFenster(tk.Tk):
    def __init__(self):
        tk.Tk.__init__(self)
        self.wm_title("Auswahlfenster") # Fenstertitel
        self.var = tk.IntVar()
        tk.Button(self, text="Start", command=self.start).pack()
        tk.Radiobutton(self, text="Strecke 1", variable=self.var, value=1).pack()
        tk.Radiobutton(self, text="Strecke 2", variable=self.var, value=2).pack()
        tk.Label(self, textvariable=self.var).pack()

    def start(self):
        print(self.var.get())
        self.destroy()

    def get_var(self):
        i = var.get()
        return i # ?

def main():
    root = AuswahlFenster()
    root.mainloop()

if __name__ == '__main__':
    main()
    print("TEST")
    
    # hier soll irgendetwas mit dem "value" von den Radiobuttons gemacht werden
    print(AuswahlFenster.get_var()) # -> funktioniert nicht
    
    # z.B. (Pseudocode ab hier):
    # if value == 1:
    	# print("A")
    # elif value == 2:
    	# print("B")

Ich habe schon einiges ausprobiert, um den Wert zu übergeben. Von allem schien mir diese Lösung hier am plausibelsten. Leider funktioniert sie trotzdem nicht.
Das bekomme ich raus:

1
TEST
Traceback (most recent call last):
File "C:\Users\MBENES\Desktop\Daten\AGV\Python Publisher\Simulator\GUI.py", line 34, in <module>
print(AuswahlFenster.get_var())
TypeError: get_var() missing 1 required positional argument: 'self'
[Finished in 2.486s]


Den TypeError verstehe ich nicht wirklich, um ehrlich zu sein. Ich dachte, dass "self" quasi auf die eigene Klasse zeigt und in der Definition der Methode genutzt wird, um mit den Attributen der eigenen Klasse zu arbeiten.

Hoffentlich ist mein Problem klar geworden und ich hoffe, dass der ein oder andere eine Lösung hat. Ich würde mich sehr freuen. :)



Liebe Grüße,
Marc
__deets__
User
Beiträge: 14528
Registriert: Mittwoch 14. Oktober 2015, 14:29

Nach dem mainloop laeuft eh erstmal kein Code. Und bei einer GUI ist das auch immer so. Du musst also deine Folge-Aktionen durch Ereignisse auf die du reagierst modellieren. Wenn du eine Variable hast, dann zB durch deren trace, in dem du dich registrieren kannst.

Und self zeigt nicht auf die eigene Klasse. Es zeigt auf die INSTANZ der Klasse.

Code: Alles auswählen

class Foo:

     def __init__(self, arg):
           self.arg = arg

a = Foo(1)
b = Foo(2)
c = Foo(3)
print(Foo.arg) # was sollte denn hier rauskommen? Du hast doch 3 Foos!
print(a.arg, b.arg, c.arg)
Soxxes
User
Beiträge: 12
Registriert: Mittwoch 28. August 2019, 14:53

Hi __deets__,

danke für deine Antwort. :)
Das heißt, ich schreibe für das Programm, welches mit dem "value" arbeiten soll, eine Methode der Klasse, die durch einen Button bspw. aufgerufen wird?
Habe ich das richtig verstanden?

Danke auch für die Aufklärung mit "self"!


Liebe Grüße,
Marc
__deets__
User
Beiträge: 14528
Registriert: Mittwoch 14. Oktober 2015, 14:29

Das ist eine Möglichkeit. Alternativ wie gesagt trace der Variable. Ob du das willst hängt von deiner gewünschten GUI ab. Erst auswählen & explizit bestätigen. Oder bei Auswahl gleich Action.
Sirius3
User
Beiträge: 17741
Registriert: Sonntag 21. Oktober 2012, 17:20

Es kommt drauf an, was das Programm tun soll. Kannst Du mehr erzählen.
Soxxes
User
Beiträge: 12
Registriert: Mittwoch 28. August 2019, 14:53

Hi __deets__,

ich will dich nicht mit dem ganen Code belästigen, aber was ich ungefähr gemacht hätte, wäre das Folgende (beispielhaft):

import tkinter as tk

Code: Alles auswählen

class AuswahlFenster(tk.Tk):
    def __init__(self):
        tk.Tk.__init__(self)
        self.wm_title("Auswahlfenster") # Fenstertitel
        self.var = tk.IntVar()
        tk.Button(self, text="Start", command=self.beenden).pack()
        tk.Radiobutton(self, text="Strecke 1", variable=self.var, value=1).pack()
        tk.Radiobutton(self, text="Strecke 2", variable=self.var, value=2).pack()
        tk.Label(self, textvariable=self.var).pack()
        tk.Button(self, text="Ausführen", command=self.programm).pack()

    def beenden(self):
        self.destroy()

    def programm(self):
       i = self.var.get()
       y = 0
       if i == 1:
           # mache irgendwas
           # z.B.:
           y = 2 + i
       elif i == 2:
          # mache irgendwas anderes
          # z.B.:
          y = 2 * i



def main():
    root = AuswahlFenster()
    root.mainloop()

if __name__ == '__main__':
    main()

Das ist jetzt nur beispielhaft, aber im Grunde soll die Auswahl im Auswahlfenster eine Entscheidung darstellen zwischen mehreren Optionen. Aufgrund der Entscheidung soll dann entweder Programm A ablaufen oder Programm B.
Geht das eleganter als das, was ich da geschrieben habe? :D Ich bin für alles offen!


Liebe Grüße,
Marc
Sirius3
User
Beiträge: 17741
Registriert: Sonntag 21. Oktober 2012, 17:20

Nutzt dieses Programm A oder Programm B auch tkinter?

Ein Knopf „Start”, der das Programm beendet?
Die Methode beenden ist überflüssig, da man an der Stelle, wo sie benutzt wird, direkt ›self.destroy‹ schreiben könnte.

›self.var‹ bzw. ›i‹ sind schlechte Variablennamen, weil sie nicht beschreiben, für was die Variable steht. Für beides wäre ›strecke‹ passender.
Soxxes
User
Beiträge: 12
Registriert: Mittwoch 28. August 2019, 14:53

Hallo Sirius3,

nein, das Programm nutzt tkinter nicht. Es braucht nur die Auswahl des Benutzers.

Die Variablen werde ich noch umbenennen, danke für den Hinweis. :)


Liebe Grüße,
Marc
Antworten