@woto: Das Hauptprogramm sollte in einer Funktion stehen. Die heisst üblicherweise `main()`. Dann fällt auf, dass in der `__init__()` auf das globale `root` zugegriffen wird, was nicht sein darf. Damit ist so ein `MyView`-Objekt ja auch gar nicht mehr flexibel nutzbar weil es dann Probleme gäbe wenn `master` und `root` nicht das selber Objekt sind.
`My` ist in 99% der Fälle ein unsinniger Namenszusatz. Wenn es nicht auch ein `OurView` oder `TheirView` gibt, hat das `my` überhaupt keine Bedeutung. Und warum heisst das Objekt dann `app`?
Namen sollten auch keine kryptischen Prä- oder Suffixe haben. Wenn man `button` meint, sollte man nicht nur `bt` schreiben. Und solange man nicht Yoda heisst, sollte man auch nicht anfangen Worte komisch umzustellen. Das ist ein `down_button` und kein `button_down`.
Ein `LabelFrame` ohne Text macht nicht wirklich Sinn, dann ist das ja einfach nur ein `Frame`. Ich sehe auch nicht warum man in den `View`, der ja auch ein `Frame` ist, noch mal einen `Frame` setzen muss. Zumal der `View` als `Frame` in dem Code auch überhaupt nicht benutzt wird, denn da fehlt der Aufruf der das layoutet. Während es keinen Sinn macht den inneren Frame als einziges Objekt in einem Grid an eine andere Stelle zu setzen als Zeile 0 und Spalte 0.
Auch die Schaltflächen sollten in Zeile 0 anfangen und nicht in Zeile 1 wenn Zeile 0 sonst nichts weiter enthält.
Wenn es im `tkinter`-Modul für Werte mit einer speziellen Bedeutung eine Konstante gibt, sollte man die auch verwenden, statt fehleranfällig diesen Wert als Zeichenkette anzugeben.
Schaltflächen haben schon von Haus aus das angegebene `relief`. Und selbst wenn sie ein anderes hätten, sollte man das nicht ändern, denn das ist ja der Wert, den der Benutzer optisch bei Schaltflächen erwartet.
Höhe und Breite von Schaltflächen sollte man nicht selbst angeben, die ergeben sich auch dem Inhalt. Und auch wenn die Breite nicht in Pixeln, sondern in Zeichen angegeben wird, ist hier nicht garantiert, dass der tatsächliche Text auch da rein passt. Die Breite ist hier mit 7 Zeichen angegeben, der längste Text hat aber 11 Zeichen. Das kann passen, muss es aber nicht.
Wenn man etwas beim Druck auf eine Schaltfläche machen will, dann muss man eine Rückruffunktion oder -methode angeben. Und die muss dann Zugriff auf die Objekte haben, die dann gebraucht werden. Also müssen mindesten die beiden Schaltflächen deren Zustand geändert werden soll, an das Objekt gebunden werden.
Zwischenstand:
Code: Alles auswählen
import tkinter
class View(tkinter.Frame):
def __init__(self, master=None):
super().__init__(
master, padx=5, pady=5, background="green", relief=tkinter.RIDGE
)
grid_options = {"padx": 5, "pady": 5, "sticky": tkinter.NSEW}
self.down_button = tkinter.Button(
self, text="runter", border=5, command=self.on_down
)
self.down_button.grid(row=0, column=0, **grid_options)
self.up_button = tkinter.Button(
self, text="rauf", border=5, command=self.on_up
)
self.up_button.grid(row=0, column=1, **grid_options)
tkinter.Button(
self, text="runter stop", border=5, command=self.on_stop
).grid(row=1, column=0, **grid_options)
tkinter.Button(
self, text="rauf stop", border=5, command=self.on_stop
).grid(row=1, column=1, **grid_options)
for i in range(2):
self.grid_columnconfigure(i, uniform="a")
def on_down(self):
self.up_button["state"] = tkinter.DISABLED
def on_up(self):
self.down_button["state"] = tkinter.DISABLED
def on_stop(self):
self.down_button["state"] = self.up_button["state"] = tkinter.NORMAL
def main():
root = tkinter.Tk()
root.title("Datenkacheln")
view = View(root)
view.pack(padx=2, pady=5)
root.mainloop()
if __name__ == "__main__":
main()
Wobei ich nicht so ganz sehe warum es zwei Stopp-Buttons geben muss.
Edit: Zum letzten Beitrag: Es macht keinen Sinn die `__init__()` in eine weitere Methode zu verschieben. `master` gibt es bereits, das braucht man nicht selbst binden. Aber das sollte man auch gar nicht benutzen, denn wie gesagt umgeht man damit das `View`-Objekt selbst als Frame *und* man layoutet Zeugs in ein übergeordnetes Widget, was man nicht macht. Am `master` hat ein Kindwidget nichts zu basteln.