5

I am designing a GUI using Python and Tkinter. All the buttons and entries required to register the user input commands are placed inside a main frame and are their child widgets.

I want to know if it is possible to disable all the input functionality from these widgets by propagating some "disable" flag from the main frame to all the input widgets. In this way, I was hoping to be able to toggle their state in a single line of code.

I believe that should be possible. Does anyone know how to do this?

zml
  • 617
  • 7
  • 14

1 Answers1

6

Tk widgets have a state configuration option that can be either normal or disabled. So you can set all children of a frame to disabled using the winfo_children method on the frame to iterate over them. For instance:

for w in app.winfo_children():
    w.configure(state="disabled")

Ttk widgets have state method which might require alternative handling. You may also want to set the takefocus option to False as well although I think that disabled widgets are automatically skipped when moving the focus (eg: by hitting the Tab key).

Edit

You can use the winfo_children and winfo_parent methods to walk the widget tree in both directions if necessary to access widgets contained in child frames for instance. For example, a simple function to visit each child of a root widget:

def visit_widgets(root, visitor):
  visitor(root)
  for child in root.winfo_children():
    visit_widgets(child, visitor)

from __future__ import print_function
visit_widgets(app, lambda w: print(str(w)))
patthoyts
  • 32,320
  • 3
  • 62
  • 93
  • 1
    I get the "unknown option '-state'" when using your code (replacing the variable "app" by my mainframe) so I guess I am using widgets which do not have that option. However, even if I add a "try:" before the w.configure function, the buttons inside the frame stay clickable. Do you have any thoughts on that? Thank you – zml Mar 13 '14 at 16:24
  • 1
    You said "buttons" and "entries" and both of those widgets support the disabled state. Even they are ttk widgets the Label and Button widgets both support this configure option. You can use 'widget.winfo_class()' to find the widget class name and see which ones are failing. If they are ttk widgets then you can also use the 'state' method, but note it takes a list of states. ie: w.state(['disabled']) or w.state(['!disabled','active']). – patthoyts Mar 13 '14 at 16:53
  • I gave those as examples, but you are right, those are the only input widgets I need to disable. However, I understand that this code only handles the child widgets. Is there an easy way to do the same to all the subsequent levels (children of the children and so on..) of the tree in a single command? – zml Mar 14 '14 at 11:33