@Kahnbein.Kai: Also wenn das so als Beispiel in einem Buch steht, würde ich mir ein anderes Buch suchen.
Sternchen-Importe sin Böse™, auch wenn die in manchen Büchern oder Tutorials gerade im Zusammenhang mit `tkinter` verwendet werden, aber das neben dem Sternchem-Import dann auch noch das `tkinter`-Modul selbst importiert wird und im Code dann beide Wege verwendet werden um auf Werte aus diesem Modul zuzugreifen, sollte in keinem Buch oder Tutorial vorkommen. Also also als erstes mal sollte der Sternchem-Import weg. `tkinter` kann man dann als `tk` importieren, damit es etwas weniger Tipparbeit gibt und der Code übersichtlich bleibt.
Auf Modulebene sollte wie sparrow ja schon anmerkte kein Code stehen, also keiner der nicht Konstanten, Funktionen, oder Klassen definiert. Das Hauptprogramm steht üblicherweise in einer Funktion die `main()` heisst. Womit der Name `main` für das `Tk`-Objekt ungünstig ist, weil das zu Verwirrungen beim Leser führen kann.
Namen sollten keine kryptischen Abkürzungen oder Prä-/Suffixe enthalten und schon gar nicht nur aus einer Abkürzung oder einem Buchstaben bestehen. `p`, `im`, `e`, `bquad`, `lb`, `lb1`, und `bende` sind keine guten Namen an denen der Leser erkennen kann was der Wert, der dahinter steckt, im Kontext des Programms bedeutet.
Wenn man das `PhotoImage`-Objekt vor dem `Label` in dem es angezeigt werden soll erstellt, dann braucht man das nicht nachträglich ändern sondern kann das Bild gleich beim Erstellen des `Label` übergeben.
Um Gleichheitszeichen von Schlüsselwortargumenten setzt man üblicherweise keine Leerzeichen. Siehe auch den
Style Guide for Python Code.
Die `ende()`-Funktion ist überflüssig weil da nur eine Methode aufgerufen wird, die man auch direkt als `command` bei dem `Button` angeben kann. Wobei ich da auch nicht `destroy()` verwenden würde, sondern einfach die `quit()`-Methode zum verlassen der GUI-Hauptschleife.
Die Funktionsnamen sind auch schlecht. `trip()` ist eine Reise und `quad()` eine Fahrzeugart. Wenn man `quadrieren()` und `triple()` meint, sollte man das auch schreiben. Wobei da die Sprachwahl ein wenig inkonsistent ist und `triple()` auch falsch ist, denn es wird ja nicht verdreifacht, sondern exponenziert.
Zudem sind die beiden Funktionen fast gleich. Das sollte so nicht sein, da würde man *eine* Funktion schreiben, bei der der Exponent als Argument übergeben wird.
Apropos Argument(e): Da es auf Modulebene keine Variablen gibt, werden Funktionen und Methoden alle Werte ausser Konstanten, als Argument(e) übergeben.
Man verwendet keine nackten ``except:``\s ohne konkrete Ausnahmen. Damit werden dann *alle* Ausnahmen behandelt, auch solche die man gar nicht erwartet. Es gibt nur wenige Möglichkeiten wirklich *alle* Ausnahmen *sinnvoll* zu behandeln. Wenn Du darauf reagieren möchtest, dass eine Zeichenkette nicht in eine Zahl umgewandelt werden kann, dann behandle a) explizit die Ausnahmen die dabei ausgelöst wird, und b) sollte der ``try``-Block nur wenig Code umfassen, nicht das die gleiche Ausnahme auch anders ausgelöst werden kann, dann aber etwas anderes bedeutet.
Werte und Zeichenketten stückelt man in Python nicht mit ``+`` und `str()` zusammen. Das ist eher BASIC als Python. In Python gibt es dafür die `format()`-Methode auf Zeichenketten und ab Python 3.6 f-Zeichenkettenliterale.
Statt eine Liste zu missbrauchen um in einem Lambda-Ausdruck mehr als eine Funktion aufzurufen, schreibt man eine Funktion die mehrere andere Funktionen aufruft.
Nun zum Problem warum das Bild verschwindet: Es gibt keine Möglichkeit bei Tk in Erfahrung zu bringen ob ein Bild noch benötigt wird oder nicht. Es liegt also an Python ob das Bildobjekt aus dem Speicher entfernt wird. Damit das nicht passiert, muss man dafür Sorgen, dass eine Referenz auf das Bild in Python erreichbar bleibt. Ein Hack um das ohne eigene Klasse zu erreichen ist das Bild einfach als Attribut irgendwo anders dran zu heften von dem man weiss, dass es besteht solange das Bild gebraucht wird. Da bietet sich das `Label`-Objekt an in dem das Bild angezeigt wird, denn solange das existiert, wird auch das Bild gebraucht.
Zwischenstand:
Code: Alles auswählen
#!/usr/bin/env python3
import tkinter as tk
from functools import partial
DIGIT_TO_SUPERSCRIPT_DIGIT = str.maketrans("0123456789", "⁰ⁱ²³⁴⁵⁶⁷⁸⁹")
def exponentiate(entry, result_label, exponent):
try:
number = float(entry.get())
except ValueError:
result = "Bitte eine Zahl eingeben"
else:
exponent_text = str(exponent).translate(DIGIT_TO_SUPERSCRIPT_DIGIT)
result = f"Ergebnis von {number}{exponent_text} = {number ** exponent}"
result_label["text"] = result
def on_exponentiate(
image_label, entry, squared_result_label, cubed_result_label
):
exponentiate(entry, squared_result_label, 2)
exponentiate(entry, cubed_result_label, 3)
entry["background"] = "#FFEA00"
image = tk.PhotoImage(file="Bild2.gif")
image_label.image = image
image_label["image"] = image
def main():
root = tk.Tk()
image = tk.PhotoImage(file="Bild.gif")
image_label = tk.Label(root, image=image)
image_label.pack()
entry = tk.Entry(root)
entry.pack()
exponentiate_button = tk.Button(root, text="Exponenzieren")
exponentiate_button.pack()
squared_result_label = tk.Label(root, text="Ergebnis: ")
squared_result_label.pack()
cubed_result_label = tk.Label(root, text="Ergebnis: ")
cubed_result_label.pack()
exponentiate_button["command"] = partial(
on_exponentiate,
image_label,
entry,
squared_result_label,
cubed_result_label,
)
tk.Button(root, text="Ende", command=root.quit).pack()
root.mainloop()
if __name__ == "__main__":
main()