Tkinter mit mehreren Klassen

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
toper
User
Beiträge: 74
Registriert: Freitag 13. April 2018, 14:37

Hallo zusammen.
Ich möchte gerne ein Programm mit Tkinter schreiben und dies auf mehrere klassen aufteilen.

In der ersten Klasse rufe ich die Klasse menu auf

Code: Alles auswählen

class menu:
    def start(Button):
        text = ["1","2","3","4"]
        for i in range(4):
            Button[i].config(text=text[i],command=lambda i=i: menu.Button_gedrueckt(i))
            Button[i].place(x=0,y=0,width=100,height=50)

       
    def Button_gedrueckt(Button_nummer):
        print(Button_nummer)
Hierbei bearbeie ich Buttons die ich in der "main" Klasse erstellt habe

Das Problem:
Das Main Programm benötigt die Button_nummer. Das heißt sobald ich einen Button drücke soll die Button_nummer an das Main Programm zurückgegeben werden.
Allerdings möchte ich kein neues Main Objekt erstellen.
Ich dachte zum Beispiel an eine 2 Seitige Assoziation, weiß aber nicht wie das geht.

Weiß jemand wie das geht oder hat vielleicht noch eine bessere Lösung?
Benutzeravatar
__blackjack__
User
Beiträge: 14052
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@toper: Du machst das genau so wie `Button`: Wer auch immer Deine Klasse benutzt muss eine Rückruffunktion übergeben die Deine Klasse dann immer aufruft wenn ein Button gedrückt wurde.

Wobei die Klasse die Du da zeigst keine Klasse ist. Da stimmt so einiges nicht, angefangen bei der Schreibweise des Namens der Klasse selbst, bis zu dem Umstand das die keine Methoden hat.

Namen werden in Python klein_mit_unterstrichen geschrieben. Ausnahmen sind Konstanten (KOMPLETT_GROSS) und Klassen (MixedCase). Die Klasse müsste also `Menu` heissen. Nur das es wie gesagt keine Klasse ist, sondern einfach nur zwei Funktionen die ohne Not in eine Klasse gestopft wurden. Das kann man einfach sein lassen, ohne das sich etwas ändert ausser dem Zugriff auf die Funktion.

Der Name `Button` ist zudem irreführend weil das ja offenbar mehr als ein Button ist, also `buttons` heissen sollte. Und `text` sollte `texts` heissen. Denn man braucht den Namen `text` dann ja für einen einzelnen Text wenn man das ``for i in range(…):`` „anti pattern“ beseitigt. Man verwendet in Python nur selten einen Laufindex um damit dann auf Sequenzen zuzugreifen. Man kann in Python direkt über die Elemente von Sequenzen iterieren. Will man ”parallel” über mehr als eine Sequenz iterieren gibt es die `zip()`-Funktion, und falls man zusätzlich eine laufende Zahl braucht, die `enumerate()`-Funktion.

Den ``lambda``-Hack mit dem Defaultwert für das Argument macht man nicht mehr seit dem es `functools.partial()` gibt.

Der `place()`-Aufruf macht mich ein bisschen sprachlos‽ Dementsprechend bin ich mir bei dem Funktionsnamen auch nicht wirklich sicher, denn ich weiss nicht so recht was der Sinn dieser Funktion ist.

Was übrig bleibt:

Code: Alles auswählen

#!/usr/bin/env python3
from functools import partial


def menu_start(buttons):
    texts = ["1", "2", "3", "4"]
    for i, (button, text) in enumerate(zip(buttons, texts)):
        button.config(text=text, command=partial(print, i))
        #
        # WTF‽
        #
        button.place(x=0, y=0, width=100, height=50)
“Vir, intelligence has nothing to do with politics!” — Londo Mollari
toper
User
Beiträge: 74
Registriert: Freitag 13. April 2018, 14:37

@__blackjack__
Erstmal vielen Dank für die Tipps mit den Benennungen.
Du hast gesagt ich soll eine Rückruffunktion übergeben. Wie genau funktioniert das?
Sirius3
User
Beiträge: 18272
Registriert: Sonntag 21. Oktober 2012, 17:20

@toper: das ist kein sinnvolles Klassendesign, wenn ein Instanz der einen Klasse zu viel Information einer anderen braucht.
Die Klasse menu ist auch gar keine Klasse, sondern einfach nur zwei Funktionen, die irgendwie zu weit eingerückt sind.
Klassen brauchen einen Zustand den sie repräsentieren, dazu brauchen sie eine __init__-Methode. Jede Methode hat deshalb auch ein `self`-Argument.
Lerne am besten von Grund auf, wie man Klassen definiert und benutzt.
Zu konkreterer Hilfe brauchen wir auch ein lauffähiges Beispiel.
Antworten