Tkinter and dialogs

D

dwelch91

I'm trying unsuccessfully to do something in Tk that I though would be
easy. After Googling this all day, I think I need some help. I am
admittedly very novice with Tk (I started with it yesterday), so I am
sure I am overlooking something simple.

The basic idea is that my application will consist of a series of modal
dialogs, that are chained together in "wizard" fashion. There will be
some processing in between dialogs, but for the most part, the user will
do some interaction with each dialog and then click "Next" or
"Previous". My thinking was that the main (root) Tk window would be
hidden and that each dialog would be modal and child to that hidden
window. Is this a reasonable way to do this in Tkinter?

I grabbed the "Dialog" class from effbot's site figuring that was good
starting point. I did modify it somewhat to convert to the grid layout
manager, based on advice in the New Mexico Tech Tkinter Reference (by
John Shipman).

When I run this (Ubuntu 6.06), I get no windows, not even the root Tk one.

Any ideas???

Thanks,

Don




#!/usr/bin/env python
from Tkinter import *

root = None

class Dialog(Toplevel):

def __init__(self, parent, title = None):
Toplevel.__init__(self, parent)
self.transient(parent)

if title:
self.title(title)

print repr(parent)
self.parent = parent
self.result = None

#body = Frame(self)
#self.initial_focus = self.body(body)
#body.pack(padx=5, pady=5)

self.initial_focus = self.body(self)

self.buttonbox()

self.bind("<Return>", self.ok)
self.bind("<Escape>", self.cancel)

self.grab_set()

if not self.initial_focus:
self.initial_focus = self

self.protocol("WM_DELETE_WINDOW", self.cancel)

self.geometry("+%d+%d" % (parent.winfo_rootx()+50,
parent.winfo_rooty()+50))

self.initial_focus.focus_set()

self.wait_window(self)


#
# construction hooks

def body(self, master):
# create dialog body. return widget that should have
# initial focus. this method should be overridden
pass

def buttonbox(self):
# add standard button box. override if you don't want the
# standard buttons

box = Frame(self)

w = Button(box, text="OK", width=10, command=self.ok,
default=ACTIVE)
w.pack(side=LEFT, padx=5, pady=5)
w = Button(box, text="Cancel", width=10, command=self.cancel)
w.pack(side=LEFT, padx=5, pady=5)

self.bind("<Return>", self.ok)
self.bind("<Escape>", self.cancel)

box.pack()

#
# standard button semantics

def ok(self, event=None):
if not self.validate():
self.initial_focus.focus_set() # put focus back
return

self.withdraw()
self.update_idletasks()
self.apply()
self.cancel()

def cancel(self, event=None):
# put focus back to the parent window
self.parent.focus_set()
self.destroy()

#
# command hooks

def validate(self):
print "validate"
return True # override

def apply(self):
print "apply"
pass # override


class WelcomeDialog(Dialog):
def body(self, master):

Label(master, text="First:").grid(row=0, sticky=W)
Label(master, text="Second:").grid(row=1, sticky=W)

self.e1 = Entry(master)
self.e2 = Entry(master)

self.e1.grid(row=0, column=1)
self.e2.grid(row=1, column=1)

self.cb = Checkbutton(master, text="Hardcopy")
self.cb.grid(row=2, columnspan=2, sticky=W)

self.w1 = Button(master, text="OK", width=10, command=self.ok,
default=ACTIVE)
#w.pack(side=LEFT, padx=5, pady=5)
self.w1.grid(row=3, column=0)
self.w2 = Button(master, text="Cancel", width=10,
command=self.cancel)
#w.pack(side=LEFT, padx=5, pady=5)
self.w2.grid(row=3, column=1)


def apply(self):
print "apply"
first = int(self.e1.get())
second = int(self.e2.get())
self.result = first, second

def buttonbox(self):
pass


def show_ui():
welcome = WelcomeDialog(root, "test1")



global root
root = Tk()
root.after_idle(show_ui)
root.mainloop()
 
F

Fredrik Lundh

dwelch91 said:
> I get no windows, not even the root Tk one.

no time to dig deeper into this right now, but the culprit is probably a
combination of this line

self.transient(parent)

and the after_idle approach to create the Dialog (Toplevel) window. the
transient call tells Tkinter to make the new dialogue window dependent
on the parent (which is the root Tk window in this case), but that
window hasn't been created yet when you get to transient, so Tk ends up
waiting for something that obviously never happens...

as a workaround, you can either remove the transient call, or insert an
explicit root.update() before the root.after_idle() call.
root = None
global root
root = Tk()

unrelated to your question: "global" is used in a local scope (a
function or method) to indicate that a variable that you assign to is a
global variable. for the full story, see

http://pyref.infogami.com/naming-and-binding

</F>
 
M

Marc 'BlackJack' Rintsch

When I run this (Ubuntu 6.06), I get no windows, not even the root Tk one.

Any ideas???

[…]

global root
root = Tk()
root.after_idle(show_ui)
root.mainloop()

What is this `after_idle()` call supposed to do? The main loop isn't
running yet. If you just call `show_ui()` you should get some windows.

The ``global`` is unnecessary by the way. It even generates a warning:

test.py:0: SyntaxWarning: name 'root' is assigned to before global
declaration

Ciao,
Marc 'BlackJack' Rintsch
 
M

madpython

dwelch91 said:
I'm trying unsuccessfully to do something in Tk that I though would be
easy. It is easy.
The basic idea is that my application will consist of a series of modal
dialogs, that are chained together in "wizard" fashion.
Didn't have time to get into the code you posted. Just think that the
solution I use might be of some help.

#!/usr/bin/env python
import Tkinter
class PrevNextPane(Tkinter.Frame):
def __init__(self,master):
self.master=master
Tkinter.Frame.__init__(self,master)

self.prvBtn=Tkinter.Button(self,text="Prev",command=self.do_prev).grid(row=0,column=0)

self.nxtBtn=Tkinter.Button(self,text="Next",command=self.do_next).grid(row=0,column=1)
def do_next(self):
self.master.paneNumber+=1
self.master.displayPane()

def do_prev(self):
self.master.paneNumber-=1
self.master.displayPane()

class Pane0(Tkinter.Frame):
def __init__(self,master):
Tkinter.Frame.__init__(self,master)
for i in range(5):
Tkinter.Entry(self).grid(row=i,column=0)

class Pane1(Tkinter.Frame):
def __init__(self,master):
Tkinter.Frame.__init__(self,master)
for i in range(5):
Tkinter.Label(self,text="Label %s"% i).grid(row=i,column=0)

class Pane2(Tkinter.Frame):
def __init__(self,master):
Tkinter.Frame.__init__(self,master)
for i in range(5):
Tkinter.Button(self,text="BtnPane2-%s"%
i).grid(row=i,column=0)

class Wizard(Tkinter.Tk):
def __init__(self):
Tkinter.Tk.__init__(self)
self.topPane=None
self.prevNextPane=PrevNextPane(self).pack(side=Tkinter.BOTTOM)
self.paneNumber=0
self.displayPane()
def displayPane(self):
if self.topPane!=None:
self.topPane.forget()
try:
self.topPane=globals()["Pane%s"% self.paneNumber](self)
except KeyError:
pass
self.topPane.pack(side=Tkinter.TOP)

if __name__=="__main__":
w=Wizard()
w.mainloop()
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,743
Messages
2,569,478
Members
44,898
Latest member
BlairH7607

Latest Threads

Top