Re: (n00b) Tkinter trouble
On Tue, Nov 15, 2011 at 10:49 PM, Chris Angelico wrote: > On Wed, Nov 16, 2011 at 2:02 PM, Jason Swails > wrote: > > Apparently I could not do what I was wanting to (state=DISABLED is not a > > valid option to Toplevel). What I wanted to do was something similar to > > what the dialogs were doing from tkMessageBox. > > Yes, that would be what you'd want. I wonder, though: Is Toplevel the > right window class? There may be a better class for a subwindow. > Again, I'm not familiar with Tkinter, but a quick google suggests that > Frame or Window might be worth looking into. Ideally, you want the > window to disable its parent and claim all events. > I think Toplevel is right. Frame isn't actually a window (a window has to be its parent), and I've never seen any documentation regarding a Window class (perhaps it's just meant to be a base class that Toplevel inherits from?). I think a separate window needs to be a Toplevel instance (or instance of a Toplevel-derived class). Pulling on the tkMessageBox example again, their base Dialog class inherits from Toplevel. In any case, I've actually found that Tkinter is relatively straightforward to learn, despite some of the bashing it's received here (admittedly I've never tried PyGTK or wxpython or any of the other toolkits because I want to keep dependencies within the stdlib as much as possible). Thanks! Jason -- http://mail.python.org/mailman/listinfo/python-list
Re: (n00b) Tkinter trouble
On Wed, Nov 16, 2011 at 2:02 PM, Jason Swails wrote: > Apparently I could not do what I was wanting to (state=DISABLED is not a > valid option to Toplevel). What I wanted to do was something similar to > what the dialogs were doing from tkMessageBox. Yes, that would be what you'd want. I wonder, though: Is Toplevel the right window class? There may be a better class for a subwindow. Again, I'm not familiar with Tkinter, but a quick google suggests that Frame or Window might be worth looking into. Ideally, you want the window to disable its parent and claim all events. ChrisA -- http://mail.python.org/mailman/listinfo/python-list
Re: (n00b) Tkinter trouble
On Tue, Nov 15, 2011 at 12:32 AM, Chris Angelico wrote: > > As a general rule, if any parent is invisible, you won't see the > child, and if any parent is disabled, you can't access the child. Yea, I'm becoming more familiar and comfortable with the GUI hierarchy as I play around. I do like how simple it is to test a concept in Tkinter (just a couple lines builds you a window with any kind of widget you want). > You > may find that there's even a one-line command that will disable the > window, open a new window, wait for the new window to close, and > automatically reenable the window - an "open modal dialog" function or > something. > Apparently I could not do what I was wanting to (state=DISABLED is not a valid option to Toplevel). What I wanted to do was something similar to what the dialogs were doing from tkMessageBox. The window didn't appear changed, but no buttons could be clicked. After looking through the tkMessageBox.py source code, I found the method I was looking for: grab_set. Essentially, I just have to have my new window call its grab_set() method to hog all events. Not really "disabling" the root window (which is why I had a hard time finding it on Google), but it's the exact behavior I was looking for. http://www.python-forum.org/pythonforum/viewtopic.php?f=15&t=4930 was helpful here. The only other approach I (successfully) tried was to use the .withdraw() method on the window during the constructor of the *new* window and execute .deiconify() on it during the new window's destroy() method (before calling Toplevel's destroy on self). I still like the first way better. Thanks! Jason -- http://mail.python.org/mailman/listinfo/python-list
Re: (n00b) Tkinter trouble
On Tue, Nov 15, 2011 at 4:18 PM, Jason Swails wrote: > Of course! Windows are widgets just like everything else is, and so can be > configured to be in the DISABLED state just like a button can. I'm not used > to this hierarchy in which the root window presides over all, yet is still a > widget just like everything else. > > But there's a lot of GUI programming that I haven't wrapped my head around > yet (which is why I'm running with this pet project -- but it's bound to be > ugly :)). Heh, I grew up on OS/2 and everything was an object. (With a few exceptions; the minimize/maximize/close buttons are all a single object, rather than being three.) It's not normal to disable the title bar while leaving the window enabled, but if you want to, you can! As a general rule, if any parent is invisible, you won't see the child, and if any parent is disabled, you can't access the child. You may find that there's even a one-line command that will disable the window, open a new window, wait for the new window to close, and automatically reenable the window - an "open modal dialog" function or something. ChrisA -- http://mail.python.org/mailman/listinfo/python-list
Re: (n00b) Tkinter trouble
On Mon, Nov 14, 2011 at 3:49 AM, Chris Angelico wrote: > On Mon, Nov 14, 2011 at 6:11 PM, Jason Swails > wrote: > > Then, I can reactivate all of the buttons in the destroy() method before > > calling the destroy() method of Toplevel on self. > > Small side point that might save you some work: Instead of disabling > and enabling all the buttons, disable the whole window. I don't know > Tkinter well enough to know if there's an easy way to create a modal > window, but the thing to do is to disable the entire window rather > than just its command buttons - that's the least astonishing[1] user > interface technique. > Of course! Windows are widgets just like everything else is, and so can be configured to be in the DISABLED state just like a button can. I'm not used to this hierarchy in which the root window presides over all, yet is still a widget just like everything else. But there's a lot of GUI programming that I haven't wrapped my head around yet (which is why I'm running with this pet project -- but it's bound to be ugly :)). Thanks! Jason -- http://mail.python.org/mailman/listinfo/python-list
Re: (n00b) Tkinter trouble
On Mon, Nov 14, 2011 at 6:11 PM, Jason Swails wrote: > Then, I can reactivate all of the buttons in the destroy() method before > calling the destroy() method of Toplevel on self. Small side point that might save you some work: Instead of disabling and enabling all the buttons, disable the whole window. I don't know Tkinter well enough to know if there's an easy way to create a modal window, but the thing to do is to disable the entire window rather than just its command buttons - that's the least astonishing[1] user interface technique. ChrisA [1] http://en.wikipedia.org/wiki/Principle_of_least_astonishment -- http://mail.python.org/mailman/listinfo/python-list
Re: (n00b) Tkinter trouble
On Sun, Nov 13, 2011 at 1:27 PM, Jason Swails wrote: > Hello, > > I'm trying my hand at creating a Tkinter application, but not having much > luck. I'm trying to have my top level window be a series of buttons with > different options on them. Every time a button is pressed, it opens up a > new window with options. While that new window is open, all of the buttons > on the original window are disabled. However, I want all of those buttons > to become active again once I quit my new window. I can't seem to > reactivate those buttons no matter what I do. > > This is the approach I'm trying: > > #!/usr/bin/env python > > from Tkinter import * > > class ActionButton(Button): >def __init__(self, frame, text): > self.frame = frame > Button.__init__(self, master=self.frame, text=text, > command=self.execute) >def execute(self): > window = Toplevel() > new_button = ActionButton(window, '2nd level button') > quit_button = Button(window, text='Quit!', command=window.destroy) > window.buttons = [new_button, quit_button] > for button in window.buttons: button.pack() > # Deactivate buttons from containing shell > for button in self.frame.buttons: button.config(state=DISABLED) > window.mainloop() > for button in self.frame.buttons: button.config(state=ACTIVE) > > > top = Tk() > top_button = ActionButton(top, 'Button on top!') > top_button.pack() > quit_button = Button(top, text='Quit', command=top.destroy) > quit_button.pack() > > top.buttons = [top_button, quit_button] > > top.mainloop() > > I'm really kind of running around in the dark here, so any advice or > explanation is appreciated. > Another approach I think will work, and that I'm going to try, is to subclass Toplevel and simply assign the higher-level frame/window as an instance attribute. Then, I can reactivate all of the buttons in the destroy() method before calling the destroy() method of Toplevel on self. Something like this: [untested] class MyToplevel(Toplevel): def __init__(self, root, **options): self.root = root Toplevel.__init__(self, options) for button in self.root.buttons: button.config(state=DISABLED) def destroy(self): for button in self.root.buttons: button.config(state=ACTIVE) Toplevel.destroy(self) This allows me to avoid running "mainloop()" on a non-root Toplevel instance, but links the re-activation of the buttons with the destruction of the child window (which was the effect I was going for). I must not understand what mainloop() does, fully (does it only make sense to run it on Tkinter.Tk()?) Thanks! Jason -- http://mail.python.org/mailman/listinfo/python-list