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