Reputation: 241
I am very new to Python and have to write a simple GUI program, which I chose to do in tkinter for simplicity.
The GUI I want should be very similar to the dialog one often experiences when installing a program on Windows (where would you like to install, what modules would you like, etc). Basically when it is run in python3.3, I want a window to appear with some options taking up most of the window and 'next', 'back' and 'cancel' buttons at the bottom; by clicking the 'next' button, the current window is closed and a new one opens which looks the same, except that it has different options (or perhaps it is the same window but its contents have been destroyed, I'm not sure which would be better). The rough layout I want is shown in this image
I have looked around for example codes which do something similar to this but have not been able to find any. I have seen this answer, but it's not quite what I want. I have used this tutorial to learn what I know about tkinter but I can't find an answer in it.
Here is my extremely poor attempt at a simplified version of what I want to do: When I run the code it creates a window with two buttons. The 'Quit' button works fine; however, when I click the 'Next' button it closes the window and opens a new one as desired but it also opens another window.
from tkinter import *
from tkinter import ttk
def win1():
mainframe = ttk.Frame(root, padding = '3 3 12 12')
mainframe.grid(column = 0, row = 0, sticky = (N, W, E, S))
mainframe.columnconfigure(0, weight = 1)
mainframe.rowconfigure(0, weight = 1)
ttk.Button(mainframe, text = 'Next', command = win2).grid(
column = 1, row = 1, sticky = W)
ttk.Button(mainframe, text = 'Quit', command = quit).grid(
column = 1, row = 2, sticky = W)
root.mainloop()
def quit():
root.destroy()
def win2():
quit()
new = Toplevel()
new.title('Window 2')
new = ttk.Frame(root, padding = '3 3 12 12')
new.grid(column = 0, row = 0, sticky = (N, W, E, S))
new.columnconfigure(0, weight = 1)
new.rowconfigure(0, weight = 1)
ttk.Button(mainframe, text = 'Next', command = win2).grid(
column = 1, row = 1, sticky = W)
root = Tk()
win1()
This gives the following error message (which I don't understand):
Exception in Tkinter callback
Traceback (most recent call last):
File "/usr/lib/python3.3/tkinter/__init__.py", line 1478, in __call__
return self.func(*args)
File "<stdin>", line 23, in win2
File "/usr/lib/python3.3/tkinter/ttk.py", line 733, in __init__
Widget.__init__(self, master, "ttk::frame", kw)
File "/usr/lib/python3.3/tkinter/ttk.py", line 553, in __init__
tkinter.Widget.__init__(self, master, widgetname, kw=kw)
File "/usr/lib/python3.3/tkinter/__init__.py", line 2078, in __init__
(widgetName, self._w) + extra + self._options(cnf))
_tkinter.TclError: this isn't a Tk applicationNULL main window
Apart from the fact that it doesn't actually do what I want, I feel like I am going about this the completely wrong way (defining the windows in a function, etc), and will run into a lot of trouble when I want to make it more complicated. Would anyone be able to rewrite my code in a better way and in a way that helps me build to more complicated programs, offer a resource for learning what I need to make the program I want or even offer advice? Thanks.
Upvotes: 1
Views: 7879
Reputation: 238131
I amended your example, with my hopefully correct understanding of what you are trying to achieve.
from tkinter import *
from tkinter import ttk
def win1():
mainframe = ttk.Frame(root, padding = '3 3 12 12')
mainframe.grid(column = 0, row = 0, sticky = (N, W, E, S))
mainframe.columnconfigure(0, weight = 1)
mainframe.rowconfigure(0, weight = 1)
ttk.Button(mainframe, text = 'Next', command = win2).grid(
column = 1, row = 1, sticky = W)
ttk.Button(mainframe, text = 'Quit', command = quit).grid(
column = 1, row = 2, sticky = W)
root.mainloop()
def quit():
root.destroy()
def win2():
root.withdraw()
new = Toplevel()
new.title('Window 2')
mainframe = ttk.Frame(new, padding = '3 3 12 12')
mainframe.grid(column = 0, row = 0, sticky = (N, W, E, S))
mainframe.columnconfigure(0, weight = 1)
mainframe.rowconfigure(0, weight = 1)
ttk.Button(mainframe, text = 'Next', command = win2).grid(
column = 1, row = 1, sticky = W)
root = Tk()
win1()
Hope this helps.
Upvotes: 2
Reputation: 33193
Your problem here is closing the root Tk window when you call quit(). Don't do that. Once you close that you have unloaded Tk and it can't process the Window system messages properly for you. Instead, if you want to create an application that is a series of dialogs, hide the root window by withdrawing it and create each dialog as a new toplevel with the hidden root toplevel as the parent.
Upvotes: 4