Zwei Fenster unabhängig voneinander schließen
Ok, du hast ja Recht, ich war jetzt einfach zu sehr auf Tk fixiert. Obwohl man hier sicher auch nicht-modale-Dialog schreiben kann was aber, wie ich annehme, nicht sehr einfach wird.
Die Sache ist eigentlich ganz einfach. Folgendes Beispiel (an das von wuf angelehnt, aber ein bißchen mehr an meinen Geschmack angepaßt
):
So, jetzt kommentiert mal in der Klasse "MyDialog" die Zeile
aus, also ändert sie zu
Jetzt tritt ein Fehler auf. Aha!
Gruß

Code: Alles auswählen
#!/usr/bin/env python
import Tkinter as tk
class MyDialog(tk.Toplevel):
def __init__(self, app_win):
tk.Toplevel.__init__(self)
self.app_win = app_win
self.title("Dialog Window")
self.geometry("+300+250")
self.label = tk.Label(self, text="Please enter something:")
self.label.pack()
self.entry = tk.Entry(self)
self.entry.pack()
self.entry.focus()
self.button_ok = tk.Button(self, text="Ok",
command= self.dialog_end)
self.button_ok.pack()
self.app_win.wait_window(self)
def dialog_end(self):
self.entry_data = self.entry.get()
self.destroy()
class MyTextfield(tk.Toplevel):
def __init__(self, app_win, message):
tk.Toplevel.__init__(self)
self.app_win = app_win
self.message = message
self.tfield = tk.Text(self,
fg = 'black',
bg = 'white')
self.tfield.insert(tk.END, message)
self.button_ok = tk.Button(self, text="Ok",
command= self.textfield_end)
self.button_ok.pack()
self.tfield.pack()
self.app_win.wait_window(self)
def textfield_end(self):
self.destroy()
class MainWin:
def __init__(self):
self.app_win = tk.Tk()
self.app_win.option_add("*font", ("Arial", 15, "normal"))
self.app_win.geometry("+250+200")
self.app_win.title("Example of Custom Dialog-Window")
self.button_dialog = tk.Button(self.app_win,
text="Click button to open dialog-window.",
command = self.create_dialog_and_show_result)
self.button_dialog.pack(padx=20, pady=20)
self.button_exit = tk.Button(self.app_win,
text = "Exit",
command = self.app_win.destroy)
self.button_exit.pack(pady=10)
self.app_win.mainloop()
def create_dialog_and_show_result(self):
self.dialog = MyDialog(self.app_win)
self.textfield = MyTextfield(self.app_win, message = "You entered:\n\n" + self.dialog.entry_data + "\n")
if __name__ == "__main__":
app = MainWin()
Code: Alles auswählen
self.app_win.wait_window(self)
Code: Alles auswählen
# self.app_win.wait_window(self)
Gruß
@problembär: Gibt es irgendeinen bestimmten Punkt auf den Du damit hinaus willst? Dass man die Funktion zum implementieren von modalen Dialogen benutzt, wurde ja nun schon mehrfach gesagt. Das ist aber auch keine magische, unerklärliche Instabilität, sondern schlicht und einfach ein offensichtlicher Logikfehler wenn man den Programmfluss so gestaltet, dass man auf ein Attribut zugreift, welches es noch nicht geben kann, wenn man nicht dafür sorgt, dass der Code der es setzt, *vorher* ausgeführt wird.
Hallo problembär (The challenger)
Danke für deine Herausforderung. BlackJack hat es schon angedeutet wo das Problem liegt. Habe mir erlaubt etwas von meinem Programmierstil in dein Skript einfliessen zu lassen. Neu wird der Dialog als modales Fenster gezeigt. Das heisst im Hauptfenster sind wärend der Dialog gezeigt wird die Schaltflächen gesperrt und unter Linux sollte der Dialog über dem Hauptfenster zu stehen kommen. Hier das modifizierte Skript:
Gruß wuf (The opponent) 
Danke für deine Herausforderung. BlackJack hat es schon angedeutet wo das Problem liegt. Habe mir erlaubt etwas von meinem Programmierstil in dein Skript einfliessen zu lassen. Neu wird der Dialog als modales Fenster gezeigt. Das heisst im Hauptfenster sind wärend der Dialog gezeigt wird die Schaltflächen gesperrt und unter Linux sollte der Dialog über dem Hauptfenster zu stehen kommen. Hier das modifizierte Skript:
Code: Alles auswählen
#!/usr/bin/env python
import Tkinter as tk
class MyDialog(tk.Toplevel):
def __init__(self, app_win, callback=None):
self.app_win = app_win
self.callback = callback
tk.Toplevel.__init__(self)
self.title("Dialog Window")
self.geometry("+300+250")
#~~ BEMERKUNG:
# Mache das Toplevel-Fenster Modal
# (Habe dies nur unter Linux getestet)
self.transient(app_win)
self.grab_set()
self.label = tk.Label(self, text="Please enter something:")
self.label.pack()
self.entry = tk.Entry(self)
self.entry.pack()
self.entry.focus()
self.button_ok = tk.Button(self, text="Ok",
command=self.dialog_end)
self.button_ok.pack()
def dialog_end(self):
entry_data = self.entry.get()
self.destroy()
if self.callback != None:
self.callback(entry_data)
class MyTextfield(tk.Toplevel):
def __init__(self, app_win, message):
tk.Toplevel.__init__(self)
self.app_win = app_win
self.message = message
self.tfield = tk.Text(self, fg='black', bg='white')
self.tfield.pack()
self.tfield.insert(tk.END, message)
self.button_ok = tk.Button(self, text="Ok", command=self.textfield_end)
self.button_ok.pack()
def textfield_end(self):
self.destroy()
class MainWin:
def __init__(self):
self.app_win = tk.Tk()
self.app_win.option_add("*font", ("Arial", 15, "normal"))
self.app_win.geometry("+250+200")
self.app_win.title("Example of Custom Dialog-Window")
self.button_dialog = tk.Button(self.app_win,
text="Click button to open dialog-window.",
command = self.create_dialog)
self.button_dialog.pack(padx=20, pady=20)
self.button_exit = tk.Button(self.app_win, text = "Exit",
command = self.app_win.destroy)
self.button_exit.pack(pady=10)
self.app_win.mainloop()
def create_dialog(self):
self.dialog = MyDialog(self.app_win, self.dialog_callback)
def dialog_callback(self, dialog_data):
#print 'Dialog-Callback', dialog_data
self.textfield = MyTextfield(self.app_win,
message="You entered:\n\n" + dialog_data + "\n")
if __name__ == "__main__":
app = MainWin()

Take it easy Mates!