Seite 1 von 1

TKinter vergleich von Strings

Verfasst: Freitag 15. Januar 2021, 14:08
von inssnach
Guten Tag,

ich möchte in einem Programm verschiedene Buttons präsentieren, diese sollen mögliche Labels mit Text füllen, aber sollte bereits Text in einem dieser Felder vermerkt sein, soll ein weiteres Feld genommen werden. Sollten bereits alle Felder ausgefüllt sein, sollten alle möglichen Button deaktiviert werden. Ich habe folgenden code geschrieben, aber anscheinend gibt es ein Problem damit zu geben Strings untereinander suffizient miteinander zu vergleichen.

Folgender Code ist bereits geschrieben (allerdings sind meine Fähigkeiten wirklich rudimentär.

from tkinter import *
from PIL import ImageTk, Image

root = Tk()
root.title ("Flop Analyzer")
root.geometry("800x800")

#Funktionen
def clicked():
Eingabe="Ah"

if Eingabe_label1 == "Bisher wurde kein Flop ausgewählt":
Eingabe_label1.set("ausgewählter Flop:{} ".format(Eingabe)+" ")
Ah_button["state"] = DISABLED
elif Eingabe_label2 == "2":
Eingabe_label2.set("{}".format(Eingabe))
Ah_button["state"] = DISABLED
elif Eingabe_label3 =="3":
Eingabe_label3.set("{}".format(Eingabe))
Ah_button["state"] = DISABLED
else:
Ah_button["state"] = DISABLED



def clicked2():
Eingabe2="As"
Eingabe_label.set("ausgewählter Flop:{} ".format(Eingabe2))


#Variablen

Eingabe_label1 = StringVar()
Eingabe_label1.set("Bisher wurde kein Flop ausgewählt")

Eingabe_label2 = StringVar()
Eingabe_label2.set("2")

Eingabe_label3 = StringVar()
Eingabe_label3.set("3")

#Frames

flop_frame =Frame(root)
flop_frame.grid(row=1,column=0)


#Button

#Ace buttons
Ah_button = Button(flop_frame, text="Ah", command=clicked)
Ah_button.grid(row=1, column=0,pady=5, padx=5)
As_button = Button(flop_frame, text="As", command=clicked2)
As_button.grid(row=1, column=1,pady=5, padx=5)
Ac_button = Button(flop_frame, text="Ac", command=clicked)
Ac_button.grid(row=1, column=2,pady=5, padx=5)
Ad_button = Button(flop_frame, text="Ad", command=clicked)
Ad_button.grid(row=1, column=3,pady=5, padx=5)


#King buttons
Kh_button = Button(flop_frame, text="Kh", command=clicked)
Kh_button.grid(row=2, column=0,pady=5, padx=5)
Ks_button = Button(flop_frame, text="Ks", command=clicked)
Ks_button.grid(row=2, column=1,pady=5, padx=5)
Kc_button = Button(flop_frame, text="Kc", command=clicked)
Kc_button.grid(row=2, column=2,pady=5, padx=5)
Kd_button = Button(flop_frame, text="Kd", command=clicked)
Kd_button.grid(row=2, column=3,pady=5, padx=5)

#Label
frame_label = Label(root, text="Pick your Flop")
frame_label.grid(row=0, column=0)

Flop_status1=Label(root, textvariable=Eingabe_label1, bd=2, width= 25,anchor=W)
Flop_status1.grid(row=4, column=0)

Flop_status2=Label(root, textvariable=Eingabe_label2, bd=2, anchor=W)
Flop_status2.grid(row=4, column=1)

Flop_status3=Label(root, textvariable=Eingabe_label3, bd=2, anchor=W)
Flop_status3.grid(row=4, column=3)


root.mainloop()



Vielleicht kann mir ja jmd dabei helfen :)

Vielen Dank

Re: TKinter vergleich von Strings

Verfasst: Freitag 15. Januar 2021, 21:57
von __blackjack__
@inssnach: Du vergleichst ein `StringVar`-Objekt mit einer Zeichenkette, das ist immer `False`. Du willst die Zeichenkette *in* dem `StringVar`-Objekt mit der anderen Zeichenkette vergleichen.

Sternchen-Importe sind Böse™. Da holt man sich gerade bei `tkinter` fast 200 Namen ins Modul von denen nur ein kleiner Bruchteil verwendet wird. Auch Namen die gar nicht in `tkinter` definiert werden, sondern ihrerseits von woanders importiert werden. Das macht Programme unnötig unübersichtlicher und fehleranfälliger und es besteht die Gefahr von Namenskollisionen.

Die Importe aus `PIL` werden nirgends verwendet.

Auf Modulebene sollte nur Code stehen der Konstanten, Funktionen, und Klassen definiert. Das Hauptprogramm steht üblicherweise in einer Funktion die `main()` heisst.

Namen werden in Python klein_mit_unterstrichen geschrieben. Ausnahmen sind Konstanten (KOMPLETT_GROSS) und Klassen (MixedCase).

Kommentare sollen dem Leser einen Mehrwert über den Code geben. Faustregel: Kommentare beschreiben nicht *was* der Code macht, denn das steht da bereits als Code, sondern warum er das macht. Sofern das nicht offensichtlich ist. Offensichtlich ist in aller Regel auch was in der Dokumentation von Python und den verwendeten Bibliotheken steht.

Man nummeriert keine Namen. Entweder will man dann bessere Namen oder gar keine Einzelnamen sondern die Werte in eine Datenstruktur zusammenfassen. Oft eine Liste.

Zum Beispiel bei den `StringVar`-Objekten. Bei denen sollte man auch nicht am Inhalt den aktuellen Zustand ermitteln, sondern den explizit als Wert modellieren.

Der Anfang der `clicked2()`-Funktion lässt erahnen, dass die fast so aussehen wird wie die `clicked()`-Funktion, nur mit einem anderen Eingabewert und das Du am Ende für jeden Button so eine nahezu identische Funktion schreiben wirst. Das macht man natürlich nicht, sondern man schreibt *eine* Funktion und parametrisiert die entsprechend.

Der Button wird in `clicked()` in *jedem* Zweig von dem ``if``/``elif``/``else`` deaktiviert. Dann muss man das nicht in jeden Zweig schreiben, sondern nur *einmal* vor oder nach diesem Konstrukt.

`frame_label` sollte eigentlich `label_frame` heissen, wenn es denn irgendwo verwendet werden würde. Vielleicht sollte der Frame verwendet werden? Falls nicht, kann der weg.

Zwischstand:

Code: Alles auswählen

#!/usr/bin/env python3
import tkinter as tk
from functools import partial
from itertools import chain, repeat


def clicked(button, card_text, var_iterator):
    variable, template = next(var_iterator, (None, None))
    if variable:
        variable.set(template.format(card_text))
    button["state"] = tk.DISABLED


def main():
    root = tk.Tk()
    root.title("Flop Analyzer")

    variables = [
        tk.StringVar(value=text)
        for text in ["Bisher wurde kein Flop ausgewählt", "2", "3"]
    ]

    frame = tk.Frame(root)
    frame.grid(row=0, column=0)
    var_iterator = zip(
        variables, chain(["ausgewählter Flop:{}   "], repeat("{}"))
    )
    for row, card_name in enumerate("AK"):
        for column, suit in enumerate("hscd"):
            text = card_name + suit
            button = tk.Button(frame, text=text)
            button["command"] = partial(clicked, button, text, var_iterator)
            button.grid(row=row, column=column, padx=5, pady=5)

    for column, variable in enumerate(variables):
        tk.Label(root, textvariable=variable, bd=2, anchor=tk.W).grid(
            row=1, column=column
        )

    root.mainloop()


if __name__ == "__main__":
    main()
Mit `tkinter.Variable`-Objekten und `functools.partial()` kommt man nicht weit. Jede nicht-triviale GUI erfordert objektorierte Programmierung (OOP). Also eigene Klassen.