Asynchronous programming, where you wait for user interactions.
In Python, based on callbacks: where you pass a function into another, with the expectation that at some point the function will be run.
You register or bind a function with/to an object on the GUI. When an event occurs, the object calls the function.
Simple Event
import tkinter
def run():
pass
# Just showing menu elements
root = tkinter.Tk()
menu_bar = tkinter.Menu(root)
root.config(menu=menu_bar)
model_menu = tkinter.Menu(menu_bar)
menu_bar.add_cascade(label="Model", menu=model_menu)
model_menu.add_command(label="Run model", command=run)
tkinter.mainloop() # Wait for interactions.
The user experience
Many people design for geeks.
Users learn by trying stuff - they rarely read manuals, so think carefully about what the default behavior of any function should be.
We need to design for the general public, but make advanced functions available for those that want them.
We should try to help the user by...
Using familiar keys and menus (e.g. Ctrl + C for copy).
Including help systems and tutorials.
Designing for users
At every stage when designing the GUI, think "is it obvious what this does?"
Make all screens as simple as possible.
Turn off functionality until needed, e.g.: model_menu.entryconfig("Run model", state="disabled")
# Until the user has chosen files, then: model_menu.entryconfig("Run model", state="normal")
Hide complex functionality and the options to change defaults in 'Options' menus.
Most of all consult and test. There is a formal element of software development called 'usability testing' in which companies watch people trying to achieve tasks with their software.