@imonbln: Hier würde ich mal ganz stark widersprechen: Globale Variablen sollte es gar nicht geben, aber wenn dann auf gar keinen Fall KOMPLETT_GROSS geschrieben, denn das ist dann ja *noch* schlechter, weil man dann mit der Erwartung bricht, dass alles was KOMPLETT_GROSS geschrieben ist, eine *Konstante* ist, und keine Variable.
``as`` beim Import ist drei mal falsch verwendet, weil da nix umbenannt wird.
Warum steht in der `main()` fast nix drin? Die `open_dialog()` sollte da inhaltlich drin stehen.
@havefun: Fenstergrössen gibt man nicht hart in Pixeln vor. Das sollte man noch nie, weil das schon immer nicht funktioniert hat, aber heutzutage bei dem Zoo von Displaygrössen und -auflösungen, und -einstellungen geht das echt gar nicht mehr. Die Fenstergrösse ergibt sich automatisch aus dem Inhalt.
„Datei öffnen“ ist für beide Schaltflächen als Text inhaltlich nicht richtig. Mit der einen wählt man eine Datei aus, mit der anderen wird sie angezeigt.
Das Programm sollte den Fall berücksichtigen, das der Benutzer keine Datei ausgewählt hat. Entweder beim Anzeigen, oder in dem man die Schaltfläche zum Anzeigen solange deaktiviert bis der Benutzer eine Datei ausgewählt hat. Also erst prüfen ob eine Datei ausgewählt wurde, dann die Datei einlesen, mit Fehlerausgabe wenn das nicht funktioniert, und dann erst die Anzeige.
Ungetestet:
Code: Alles auswählen
#!/usr/bin/env python3
import tkinter as tk
from pathlib import Path
from tkinter import filedialog, messagebox, ttk
def select_file(filename_var):
filename_var.set(
filedialog.askopenfilename(
title="Datei öffnen",
initialdir=Path.home().absolute(),
filetypes=(("text files", "*.txt"), ("All files", "*.*")),
)
)
def show_file(master, filename_var):
filename = filename_var.get()
if filename:
try:
content = Path(filename).read_text(encoding="utf-8")
except IOError as error:
messagebox.showerror(
"E/A-Fehler",
f"Die Datei {filename} konnte nicht gelesen werden.\n{error}",
)
else:
window = tk.Toplevel(master)
window.title(filename)
menu = tk.Menu(window)
window.config(menu=menu)
file_menu = tk.Menu(menu)
file_menu.add_command(label="Exit", command=window.destroy)
menu.add_cascade(label="Datei", menu=file_menu)
textbox = tk.Text(window)
textbox.pack(expand=True)
textbox.insert(tk.END, content)
else:
messagebox.showerror(
"Keine Datei gewählt",
"Es muss eine Datei zur Anzeige ausgewählt werden!",
)
def main():
root = tk.Tk()
root.title("Tkinter Open File Dialog")
root.resizable(False, False)
filename_var = tk.StringVar(value="")
ttk.Button(
root, text="Datei auswählen", command=lambda: select_file(filename_var)
).pack(expand=True)
ttk.Button(
root,
text="Datei anzeigen",
command=lambda: show_file(root, filename_var),
).pack(expand=True)
root.mainloop()
if __name__ == "__main__":
main()
Ganz allgemein kann man zu GUIs sagen, dass man bei jeder nicht-trivialen GUI nicht um objektorientierte Programmierung herum kommt, also man muss dafür eigene Klassen schreiben können. Nur bei sehr einfachen Sachen kommt man noch mit Closures aus. In diesem Beispiel hier konkret hat man noch Glück, dass ``tkinter`` die Tcl-Variablen in Objekte verpackt, weil man das braucht wenn man ”Listener” dafür registrieren will, weil in Tcl jede Variable ein ”Observable” ist, um das mal in Entwurfsmustern zu formulieren. Und das man maximal zwei Werte bei den Aufrufen weiter-/durchreichen muss.
Der Hinweis bezieht sich nicht nur auf Schule/Studium/Ausbildung und Hausaufgaben, sondern ganz allgemein. Zumal wir das ja auch alles nicht nachprüfen können, ob das hilflose nette Mädchen nicht nur Typ ist der denkt die Computernerds würden sich darum reissen ”ihr” bei den Hausaufgaben zu ”helfen”. Es ist manchmal erstaunlich wie viel Zeit und Energie manche Leute da rein stecken sich Komplettlösungen zu erbetteln, wo sie in weniger Zeit und mit weniger Energie die Aufgabe dreimal hätten selbst lösen können.
Das ist nicht gegen Dich persönlich gerichtet, man hat halt so seine Erfahrungen, und ist entsprechend misstrauisch wenn Eltern oder Grosseltern mit Aufgaben der Kinder oder Enkelkinder hier nach Lösungen fragen.