Probably the real answer to converting a non-GUI program is to truly convert it—
restructure it to initialize widgets on startup, call mainloop once to start event processing
and display the main window, and move all program logic into callback functions trig-
gered by user actions. Your original program’s actions become event handlers, and your
original main flow of control becomes a program that builds a main window, calls the
GUI’s event loop once, and waits.
This is the traditional way to structure a GUI program, and it makes for a coherent user
experience; windows pop up on request, instead of showing up at seemingly random
times. Until you’re ready to bite the bullet and perform such a structural conversion,
though, there are other possibilities. For example, in the ShellGui section earlier in this
chapter, we saw how to add windows to file packing scripts to collect inputs (Exam-
ple 10-5 and beyond); later, we also saw how to redirect such scripts’ outputs to GUIs
with the GuiOutput class (Example 10-13). This approach works if the non-GUI oper-
ation we’re wrapping up in a GUI is a single operation; for more dynamic user inter-
action, other techniques might be needed.
It’s possible, for instance, to launch GUI windows from a non-GUI main program, by
calling the tkinter mainloop each time a window must be displayed. It’s also possible to
take a more grandiose approach and add a completely separate program for the GUI
portion of your application. To wrap up our survey of GUI programming techniques,
let’s briefly explore each scheme.
Popping Up GUI Windows on Demand
If you just want to add a simple GUI user interaction to an existing non-GUI script
(e.g., to select files to open or save), it is possible to do so by configuring widgets and
calling mainloop from the non-GUI main program when you need to interact with the
user. This essentially makes the program GUI-capable, but without a persistent main
window. The trick is that mainloop doesn’t return until the GUI main window is closed
by the user (or quit method calls), so you cannot retrieve user inputs from the destroyed
window’s widgets after mainloop returns. To work around this, all you have to do is be
sure to save user inputs in a Python object: the object lives on after the GUI is destroyed.
Example 10-22 shows one way to code this idea in Python.
Example 10-22. PP4E\Gui\Tools\mainloopdemo.py
"""
demo running two distinct mainloop calls; each returns after the main window is
closed; save user results on Python object: GUI is gone; GUIs normally configure
widgets and then run just one mainloop, and have all their logic in callbacks; this
demo uses mainloop calls to implement two modal user interactions from a non-GUI
main program; it shows one way to add a GUI component to an existing non-GUI script,
without restructuring code;
"""
from tkinter import *
from tkinter.filedialog import askopenfilename, asksaveasfilename
More Ways to Add GUIs to Non-GUI Code | 647