GUI Wizard: flow control?

djw donald.welch at hp.com
Tue Aug 31 12:46:45 EDT 2004


David Chan wrote:

> Hi,
> 
> I'm trying to use python to create GUI wizards, i.e. sequences of dialog
> boxes with <BACK and NEXT> buttons.  Since I want to re-use some of the
> dialog boxes in different wizards, I want to have a main function which
> calls each dialog box, much like this:
> 
>     def select_item():
>         """runs GUI wizard to select item"""
> 
>         client = show_client_dialog()
>         job = show_job_dialog(client)
>         invoice, rate = show_invoice_dialog(job)
>         item = choose_item_dialog(invoice, rate)
>         return item
> 
> This works fine until you want to implement the <BACK button, which should
> return to the previous dialog.  Theoretically, what I'd really like is to
> be able to jump backwards through the control flow, like this:
> 
>     class GoBack(Exception): pass
>     def select_item():
>         """runs GUI wizard to select item - can go <BACK"""
>         back = HERE
>         client = show_client_dialog()
> 
>         try: job = show_job_dialog(client)
>         except GoBack: back.goto()
>         back = HERE
> 
>         try: invoice, rate = show_invoice_dialog(job)
>         except GoBack: back.goto()
>         back = HERE
> 
>         try: item = show_item_dialog(invoice, rate)
>         except GoBack: back.goto()
> 
>         return item
> 
> But I couldn't find a way of doing anything like that.  You could do
> something almost as unhorrible with nested breaks:'
> 
>     class GoBack(Exception): pass
>     def select_item():
>         """runs GUI wizard to select item - can go <BACK"""
>         CLIENT: while 1:
>             client = show_client_dialog()
>             
>             JOB: while 1:
>                 try: job = show_job_dialog(client)
>                 except GoBack: continue CLIENT
> 
>                 INVOICE: while 1:
>                     try: invoice, rate = show_invoice_dialog(job)
>                     except GoBack: continue JOB
>                     
>                     try: item = show_item_dialog(invoice, rate)
>                     except GoBack: continue INVOICE
>                     break CLIENT
> 
> Or you could do all the flow control manually in a "do_wizard" function
> and make the caller create a horrible data structure instead of writing
> readable code:
> 
>     calls = [
>         {'meth': show_client_dialog, 'args': [], 'ret': ['client']},
>         {'meth': show_job_dialog, 'args': ['client'], 'ret': ['job']},
>         {'meth': show_invoice_dialog, 'args': ['job'], 'ret': ['invoice',
>         {'rate']}, 'meth': show_item_dialog, 'args': ['invoice', 'rate'],
>         {'ret': ['item']},
>     ] # this just says: "client = show_client_dialog()", etc.
>     do_wizard(calls, locals())
> 
> 
> But this is too hideous to deploy, because I might have to remember what
> it does in six months :-)
> 
> Can anyone suggest something better, or should I abandon my goal of having
> a main function which calls each dialog box?
> 
> Many thanks,

I always code this sort of situation up as a simple state machine. Each
NEXT/BACK button controls the next state, each state being the display of a
particular dialog. A state machine can be a good candidate for flow control
that has to go "forwards" and "backwards".

-Don




More information about the Python-list mailing list