Formatting logically nested actions -- Pythonic way?

  • Thread starter Alf P. Steinbach
  • Start date
A

Alf P. Steinbach

Hi.

I discovered with tkinter the registration of widgets with layout managers
(tkinter "geometry" managers, e.g. calls to pack()) needs to be done very
hierarchically.

And this leads to hierarchical code, which would be nice to indicate by
indenting, but oops, indenting in Python is syntactically significant...

So first I thought of one routine per widget creation & layout registration, but
that was very ugly and verbose. Then thought of simply using semicolons but I
didn't even try that, because I imagined the sheer ugliness. Then I sort of
landed on the solution below, but although using the language to define a kind
of special purpose mini-language is common in C++ and Lisp I haven't seen so
much of that in Python examples, and so I wonder whether this is Pythonic or
perhaps so extremely un-Pythonic (unconventional) that it's scary -- I mean,
calls that do nothing whatsoever, but I think of *visual structure* as very
important here and IMHO (disregarding Pythonicity issues) worth the overhead...

<code>
import tkinter as tk
import contextlib

@contextlib.contextmanager
def this( object ):
yield object

window = tk.Tk()
window.title( "Picture presentation test" )

with this( tk.Frame() ) as display_area:
pic = tk.PhotoImage( file = "lightbulb_off.gif" )
with this( tk.Label( display_area, image = pic ) ) as pic_display:
pic_display.pack( side = "left" )
with this( tk.Frame( display_area, width = 500 ) ) as interaction_area:
with this( tk.Label( interaction_area ) ) as status_line:
status_line.config( text = "The switch is OFF" )
status_line.pack( anchor = "w" )
with this( tk.Button( interaction_area ) ) as toggle_button:
toggle_button.config( text = " Toggle it " )
toggle_button.pack( anchor = "w" )
interaction_area.pack( side = "left" )
display_area.place( relx = 0.5, rely = 0.5, anchor = "center" ) # Centered

window.mainloop()
</code>


Cheers,

- Alf

PS: I see a non-functional width specification in there. Just forgot to remove
that. And better with code as-is straight from editor than fixing up manually!
 
S

sturlamolden

And this leads to hierarchical code, which would be nice to indicate by
indenting, but oops, indenting in Python is syntactically significant...

I've seen this with OpenGL as well. Intendation between glBegin and
glEnd can be achieved with a context manager that calls glBegin in
__enter__ and glEnd in __exit__. Same thing for glColor* and other
functions that set state attributes: call glPushAttrib in __enter__
(before setting new state) and glPopAttrib in __exit__.

Context managers (i.e. with statement) should be used for this, as it
guards against havoc from exceptions. If a context manager is used to
call glPushAttrib and glPopAttrib, a raised exception cannot leave
OpenGL's colour bit and colour stack in an undefined state by skipping
glPopAttrib. The with statement is not just a pritty printer for your
code.

I don't see anything wrong with using context managers for tkinter as
well. But personally I prefer to design GUIs using tools like
wxFormBuilder, GLADE or QtDesigner.
 
L

Lie Ryan

Hi.

I discovered with tkinter the registration of widgets with layout
managers (tkinter "geometry" managers, e.g. calls to pack()) needs to be
done very hierarchically.

And this leads to hierarchical code, which would be nice to indicate by
indenting, but oops, indenting in Python is syntactically significant...

So first I thought of one routine per widget creation & layout
registration, but that was very ugly and verbose. Then thought of simply
using semicolons but I didn't even try that, because I imagined the
sheer ugliness. Then I sort of landed on the solution below, but
although using the language to define a kind of special purpose
mini-language is common in C++ and Lisp I haven't seen so much of that
in Python examples, and so I wonder whether this is Pythonic or perhaps
so extremely un-Pythonic (unconventional) that it's scary -- I mean,
calls that do nothing whatsoever, but I think of *visual structure* as
very important here and IMHO (disregarding Pythonicity issues) worth the
overhead...

maybe you can extend it a bit and make it more useful by auto-packing
the widget when the with-block ended. As for the case when you need to
pass arguments to the packer, perhaps the packing manager's argument
could be turned into an attribute like so:

import tkinter as tk

root = tk.Tk()
with Place(root, tk.Frame()) as display_area:
pic = tk.PhotoImage( file = "lightbulb_off.gif" )
with Pack(display_area, tk.Label) as pic_display:
pic_display.image = pic
# or perhaps just pic_display.side = "left"
pic_display.pack_side = "left"
with Pack(display_area, tk.Frame) as interaction_area:
interaction_area.width = 500
with Pack(interaction_area, tk.Label) as status_line:
status_line.text = "The switch is OFF"
status_line.pack_anchor = "w"
with Pack(interaction_area, tk.Button) as toggle_button:
toggle_button.text = " Toggle it "
toggle_button.pack_anchor = "w"
interaction_area.pack_side = "left"
display_area.place_relx = 0.5
display_area.place_rely = 0.5
display_area.place_anchor = "center"

something like this would make working with GUI much less painful...
 

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,995
Messages
2,570,230
Members
46,819
Latest member
masterdaster

Latest Threads

Top