Python tkinter klasse ausführen nach abfrage über scale

Fragen zu Tkinter.
Antworten
Duardo
User
Beiträge: 54
Registriert: Mittwoch 2. Juli 2014, 16:56

Hallo,

ich habe ein Programm, mit dem ich mithilfe von übereinander gestapelten Frames "neue Seiten" erezugen kann. Beim Schieberegler kann man einen Wert "eingeben" und diesen auf Knopfdruck (button1) einlesen lassen. Nun ist das Problem, dass ich noch einen Befehl definiert habe, der eine Abfrage der eingelesenen Zahl (vom Schieberegler) durchführt und dann eine bestimmte Klasse öffnen soll. Nun soll dieser Befehl ebenfalls über button1 laufen.

Nun sind meine Fragen: Wie führe ich zwei Befehle mittels eines Buttons aus?
Wie führe ich die jeweilige Klasse aus?
Ist mein Vorhaben überhaupt möglich?
Schonmal danke im voraus. :)

Code: Alles auswählen

import tkinter as tk
from tkinter import *
import random

class SampleApp(tk.Tk):
    def __init__(self, *args, **kwargs):
        tk.Tk.__init__(self, *args, **kwargs)

        container= tk.Frame(self)
        container.pack(side="top", fill="both", expand=True)
        container.grid_rowconfigure(0, weight=1)
        container.grid_columnconfigure(0, weight=1)

        self.frames={}
        for F in (fenster, auswahl, information1, information2, mode1, mode2, scale0, scale1):
            frame= F(container, self)
            self.frames[F]=frame
            frame.grid(row=0, column=0, sticky="nsew")

        self.show_frame(fenster)

    def show_frame(self, c):
        frame=self.frames[c]
        frame.tkraise()

class fenster(tk.Frame):
    def __init__(self, parent, controller):
        tk.Frame.__init__(self, parent)

        label=tk.Label(self, text="Das ist die Startseite")
        label.pack(side="top", fill="x", pady=10)

        button=tk.Button(self, text="Start",
                                command=lambda: controller.show_frame(auswahl))
        button.pack()

class auswahl(tk.Frame):
    def __init__(self, parent, controller):
        tk.Frame.__init__(self, parent)

        infbutton1=tk.Button(self, text="Information zu 1",
                                     command=lambda: controller.show_frame(information1))
        infbutton1.pack()

        infbutton2=tk.Button(self, text="Information zu 2",
                                     command=lambda: controller.show_frame(information2))
        infbutton2.pack()

        mode1button=tk.Button(self, text="Modus 1",
                                      command=lambda: controller.show_frame(mode1))
        mode1button.pack()

        mode2button=tk.Button(self, text="Modus 2",
                                      command=lambda: controller.show_frame(mode2))
        mode2button.pack()
                    

class information1(tk.Frame):
    def __init__(self, parent, controller):
        tk.Frame.__init__(self, parent)
        label=tk.Label(self, text="jo")
        label.pack(side="top", fill="x", pady=10)
        button=tk.Button(self, text="Zurück",
                                 command=lambda: controller.show_frame(auswahl))
        button.pack()

class information2(tk.Frame):
    def __init__(self, parent, controller):
        tk.Frame.__init__(self, parent)
        label=tk.Label(self, text="jo")
        label.pack(side="top", fill="x", pady=10)
        button=tk.Button(self, text="Zurück",
                            command=lambda: controller.show_frame(auswahl))
        button.pack()

class mode1(tk.Frame):
    def __init__(self, parent, controller):
        tk.Frame.__init__(self, parent)
        label=tk.Label(self, text= "Stellen Sie eine beliebige Frage. Wenn Sie bereit sind drücken Sie auf 'OK'")   #Text1/Label für mode1
        label.pack(side="top", fill="x", pady=10)
        def ok():
            a=random.randint(1,5)
            if a==1:
                label=Label(text="Ja")            #Label antworten für mode1
                label.pack(side="top", fill="x", pady=10)
            elif a==2:
                label=Label(text="Nein")
                label.pack(side="top", fill="x", pady=10)
            elif a==3:
                label=Label(text="Vielleicht")
                label.pack(side="top", fill="x", pady=10)
            elif a==4:
                label=Label(text="Auf jeden Fall")
                label.pack(side="top", fill="x", pady=10)
            elif a==5:
                label=Label(text="Auf keinen Fall")
                label.pack(side="top", fill="x", pady=10)
                        
        okknopf=Button(self, text="OK", command=ok)  #Der ok-Knopf
        okknopf.pack()

        button=tk.Button(self, text="Zurück",
                            command=lambda: controller.show_frame(auswahl))
        button.pack()

class mode2(tk.Frame):
    def __init__(self, parent, controller):
        tk.Frame.__init__(self, parent)

        label=Label(self, text="Suchen Sie sich aus, wie viele Wörter Sie haben möchten!")
        label.pack()
                
        def antmenge(self):
            mant["text"]="Mögliche Antworten: " \
                + str(antmengen.get()) + " "

        mant=Label(self, text="Mögliche Antworten: 0 Wörter", width=25)
        mant.pack()

        antmengen=IntVar()
        antmengen.set(0)

        antm=Scale(self, width=20, length=200, orient="vertical", from_=0, to=1,
        resolution=1, tickinterval=10, label="Wörter", command=antmenge(self),
        variable=antmengen)
        antm.pack()

        button=tk.Button(self, text="Zurück",
                                 command=lambda: controller.show_frame(auswahl))
        button.pack()

        button1=tk.Button(self, text="Ok", command=antmenge(self))
        button1.pack()

        def abfrage():
            if antmengen.get()==0:
                        scale0(tk.Frame)

            elif antmengen.get()==1:
                        scale1(tk.Frame)
                
class scale0(tk.Frame):
    def __init__(self, parent, controller):
        tk.Frame.__init__(self, parent)
        label=tk.Label(self, text="Es muss mindestens eine Antwort sein")
        label.pack(side="top", fill="x", pady=10)
        button=tk.Button(self, text="Zurück",
                            command=lambda: controller.show_frame(mode2))
        button.pack()

class scale1(tk.Frame):
    def __init__(self, parent, controller):
        tk.Frame.__init__(self, parent)
        label=tk.Label(self, text="Wort1")
        label.pack(side="top", fill="x", pady=10)
        wort1auf=Entry(self)
        wort1auf.pack()
        def ok3():     
            a=random.randint(1,1)
            if a==1:
                label2ant1=Label(self, text=" ")            #Label antworten für mode1
                label2ant1.pack()
                def wort1aufein():
                    label2ant1.configure(text=(wort1auf.get()))
                wort1aufein()
        button1=Button(self, text="Antworten", command=ok3)
        button1.pack()

        button=tk.Button(self, text="Zurück",
                            command=lambda: controller.show_frame(mode2))
        button.pack()
                

if __name__== "__main__":
    app=SampleApp()


    app.mainloop()

BlackJack

@Duardo: Das ist ziemlich viel Quelltext und mir ist nicht klar was das konkrete Problem ist. Der Ausdruck „Klasse öffnen” macht keinen Sinn. Was meinst Du damit?

Der Quelltext hält sich nicht an den Style Guide for Python Code was Namenskonventionen und Leerzeichen angeht und ist damit für Python-Programmierer schwerer zu lesen als es notwendig wäre. Insbesondere das Klassennamen mit einem Kleinbuchstaben anfangen solltest Du ändern.

Das auf den Inhalt vom `tkinter`-Modul einmal über den Namen `tk` zugegriffen wird, aber dann auch noch mal alle 190+ Namen durch den Sternchen-Import in das Modul gekippt werden ist verwirrend. Den Sternchen-Import solltest Du loswerden.

Namen sollten dem Leser verraten was der Wert im Kontext des Programms bedeutet. Einbuchstabige Namen und Abkürzungen tun das nur in seltenen Fällen. Bei vielen Namen in dem Quelltext muss man rätselraten und/oder nachsehen wo der Name definiert wurde um zu verstehen was er bedeutet.

Namen zu nummerieren ist auch ein Zeichen für ein Entwurfsproblem. In solchen Fällen will man oft statt einzelner Namen eine Datenstruktur verwenden. Oder das man sich vielleicht mal eine Minute Zeit nehmen sollte vernünftige Namen zu finden.

Für die Frames in `SampleApp` würde ich nicht die Datentypen der einzelnen Frames als Schlüssel verwenden. Die Exemplare gehen auch als Schlüssel und man nimmt sich nicht die Freiheit mehr als ein Exemplar vom selben Typ zu verwenden.

Das jeder Typ Wissen über andere Typen zu denen gewechselt werden kann hat und das `SampleApp` alle Typen kennt, macht das ganze ziemlich unflexibel. Dafür würde ich wie im letzten Absatz geschrieben sowieso nicht die Typen verwenden und ich würde die Verbindungen nich in den Typen kodieren, sondern das ganze von ”aussen verdrahten”. Dann ist es wesentlich einfacher das an der einen Stelle im Quelltext zu ändern, wo die Seiten der `SampleApp` verbunden werden.

Die ganzen lokalen Funktionen sind ungewöhnlich. Insbesondere wenn man sowieso schon Klassen verwendet, macht es wenig Sinn das mit Closures zu vermischen, die in Python nicht als Ersatz für Klassen verwendet werden, eben weil man ja schon Klassen hat.

In `mode2.__init__()` fehlen in der lokalen `abfrage()`-Funktion beim erstellen der der `scale()`-Exemplare ganz offensichtlich jeweils das Argument `controller`. Und als `parent` die *Klasse* `tk.Frame` zu übergeben wird auch nicht funktionieren. Überhaupt verstehe ich nicht warum Du an der Stelle neue Exemplare erstellen willst‽

Von der Programmlogik her könnte man den Schieberegler auch so erstellen das 0 gar nicht erst als Eingabe möglich ist, dann muss man das auch nicht testen und den Benutzer darüber informieren. Spart einen Frame im Programm.
Antworten