APC Australia

Python coding – Part 8: Making GUI apps

This month, Darren Yates begins a gentle look at how to create Graphics User Interface (GUI) apps in Windows using the Python programmin­g language.

-

If you’re interested in tech, learning to code is one of the best things you’ll ever do, giving you skills that not only make you more employable, but also allow you to ‘open the bonnet’ and see how stuff works. So far in this series, we’ve covered the basics you need to create a range of Python apps, from variables to file operations and even classes. This month, we make the leap from command-line to GUI apps that will run on any Windows computer.

COMMAND-PROMPT VS GUI

All the apps we’ve written so far in this series run in the command-prompt window and despite what some may consider a boring façade, the command-prompt is a great way to start coding because the ‘user interface’ is taken care of for you. All you need are print() and input() functions and you’re away.

But when you start writing GUI apps, you get to decide where everything goes — the buttons, the textboxes, radio buttons and more. It also means you now have two coding streams to consider — the app’s functional code or ‘algorithm’ and the user interface design. Which do you code first — the app algorithm or the user interface? It depends, but if you’re designing software profession­ally, you’d more likely start by consulting stakeholde­rs — the people who’ll have to use your software — to find out the features and functions they require, then build your software around that, take it back to stakeholde­rs for checking and so on. Still, rather than get bogged on the ‘systems design and analysis’ road, we’ll just cover the nuts and bolts of creating Python GUI apps.

TRY-IT-AND-SEE

If you play around with Microsoft’s Visual Studio or Google/JetBrains’ Android Studio, you’ll find these integrated developmen­t environmen­ts (IDEs) come with layout editors or ‘GUI builders’ that are a bit like desktop publishing for apps — you can drag and drop controls onto the app window as you want them to appear in the real thing. However, Python’s IDLE developmen­t environmen­t doesn’t have this, but that’s not a bad thing when you first start — because you’re forced to code manually and see what

“You now have two coding streams to consider — the app’s functional code or ‘algorithm’ and the user interface design.”

works. This way, you get to understand what the GUI code actually does. Sure, once you’re more familiar with things, move onto other more feature-rich IDEs (as most people do). But to begin with, the more you understand how your code works, the easier you’ll find coding in the future.

CREATING A WINDOW

Python, on its own, doesn’t know anything about GUI apps, but the power of Python is in its modules or ‘libraries’ that enable you to bolt into your code almost any functional­ity you can think of. GUI apps are no exception to this and there are at least a dozen different libraries you can add that handle GUI developmen­t alone. However, since the IDLE environmen­t itself is written in Python, it comes with a GUI library bundled called ‘tkinter’. It’s actually a programmin­g language of its own called ‘tcl’ with an extension called ‘tk’ for creating GUI controls or ‘widgets’. Combined, they’re known as ‘tcl/tk’ and come preinstall­ed in many Linux/Unix distros, including Mac OS X (although, you need to be careful here — tinyurl.com/lvrb835).

To create a simple ‘hello world’ Python GUI app, we need to import tkinter (short for ‘tk interface’) into our app and in IDLE on Windows, we do that with: import tkinter

Last month, we introduced the concept of ‘object-oriented programmin­g’ (OOP) and ‘classes’, so let’s use one here: import tkinter class GuiApp: def __init__(self): self.window = tkinter.Tk() self.window. geometry(‘400x300’) tkinter.mainloop() my_ gui_ app = GuiApp()

The class, called ‘GuiApp’, defines what the interface will look like, which here, is just a blank window. We define it inside the initialisa­tion (“__init__”) or ‘constructo­r’ function and fire up tkinter’s mainloop() function to display it. After that, we create a copy or ‘instance’ of the GuiApp class and call it ‘my_ gui_app’, which automatica­lly creates the window and displays it. The size of the window in pixels is set by the geometry() function and the character array parameter ‘400x300’.

TEXT LABELS

An empty window isn’t particular­ly useful, so open up ‘helloworld.py’ in the IDLE editor from this month’s source code pack and we’ll start adding widgets, two of the most common being labels and buttons. Labels let you add text to a window, buttons add user-control commands for further actions. To add a label, you use tkinter’s ‘Label’ function — it has a number of parameters, most of which are optional, except the first, which identifies where the label belongs.

Labels, like other tk widgets, have to belong somewhere, they have to have a ‘parent’ widget. Here, we assign the label to self.window, which is the root tk widget for this class. You also must specify the text you want the label to display. You have two options for this – you can use a fixed string or ‘literal’, such as “hello world”, or you can assign a variable.

Remember us saying previously that tkinter uses the tcl language? To pass text to the label, we need to create an instance of a tk variable class called ‘StringVar’ (String Variable):

self.labelText = tkinter. StringVar()

self.labelText.set(“Hello world”)

self.label = tkinter. Label(self.window, textvariab­le=self.labelText, font=”Arial 24 bold”)

self.label.pack()

We then assign text to the variable using StringVar’s set() function. Lastly, we call the pack() function to add the

label to the window, which invokes the layout manager. Tkinter has three main layout managers — pack, grid and place.

‘Pack’ brings in the various widgets you code and automatica­lly places them within the window, using only the space needed. However, the alignment may change depending on how the user changes with window size. ‘Grid’ uses a table-like arrangemen­t, aligning widgets into rows and columns. It’s simple enough, but fairly rigid. ‘Place’, on the other hand, lets you decide exactly where a widget sits in the window, down to the pixel. It sounds great, but if users can resize your app window, those fixed-position widgets won’t neatly realign of their own accord. So while it’s versatile, ‘place’ requires more work to always look right (unless you lock your app window size).

COMMAND BUTTONS

Command buttons are the most common app control and adding a button is similar to adding a Label. In our ‘helloworld.py’ example, we create an instance of tkinter’s Button object and assign it to a new object ‘self.buttonOK’. The first parameter is, again, the parent widget, followed by the text you want the button to show. After that, you indicate the function you want launched when the button is pressed (in this case, it’s a function we create called ‘changeLabe­l’). Again, we ‘pack’ the buttonOK object into the self.window widget and finally, run the main tkinter loop.

We haven’t created the ‘changeLabe­l’ function yet, so let’s do it now. We start by defining it as a separate classmembe­r function using the ‘def’ keyword and here, just to keep things simple, we’ll get it to just change the above label text to read: ‘Hello yourself!’ So the link between the command button and the function is the ‘command’ parameter in the Button() function initialisa­tion (remember the ‘self’ prefix).

TEXT ENTRY

The other common widget is the Entry widget, which provides the user a single-line text entry area. Open up ‘entername.py’ and you’ll see the only mandatory parameter is, again, the parent widget. Now to get hold of the text the user enters, use the get() function, which returns the text as a string object — in this example, we’re changing the label text by incorporat­ing the contents of this string object as a personal greeting.

CENTRING THE APP WINDOW

One thing you might want to adjust straight away is the location of your app on the computer screen. At the moment, our apps are all located near the top-left corner, by default. Python and tkinter don’t have a function to auto-centre app windows, but you can code your own using built-in parameters. First, decide on the app window frame size you want by choosing a ‘width’ and ‘height’, in pixels. Next, get tkinter to return the current screen width and height, again, both in pixels, using the functions winfo_screenwidt­h() and winfo_screenheig­ht(). Now, halve the screen width and subtract half the app window width, then halve the screen height and subtract half the app window height and you’ll have the top-left corner coordinate­s that guarantee your app will appear front-and-centre.

KNOW YOUR TIMES TABLES

OK. We’ve now got some basics under our belt — we can create a window with a label, command button and user text-entry widget. Now let’s use some of the other Python knowledge we’ve gathered over the last few issues and create a GUI app. Nothing too complicate­d, just something to get started. And remember, this is just one way to do it — there’s always more than one way to code an app.

Our new ‘quiz.py’ app is a basic times-table quiz that asks you to answer random times-table questions and keeps track of the number of questions you get right, along with the total number asked. It builds on what we’ve just learned, but also adds

in some extra tweaks. For example, adding a title to the app window. You add it to your tk() object using the title() function — just give it a string of text and that’s it.

The app also has three labels — labelQuest­ion, labelCheck and labelScore. Note also the new font parameter — you can change the font type and size with the ‘font’ string, starting with the font name, its point-size and any font additions (bold, italics and so on).

PACKING ORDER MATTERS

One other thing to remember — the order in which you enter the ‘pack()’ statements into your code is the order they’ll appear in your app. You can put these statements wherever you want (within reason), but the order matters. The same also occurs for ‘grid()’. However, since ‘place()’ allows you to set the exact positionin­g, widget order doesn’t matter in that instance.

CLASS FUNCTIONS

At the start of this masterclas­s, we mentioned that GUI apps require you to consider two streams — the GUI design code and your app functional­ity. The quiz app functional­ity here mostly takes place in the two class functions, checkAnswe­r() and newQuestio­n().

The app begins by running newQuestio­n() to generate a new times-table question. This consists of generating two random integers between zero and 12 and assigning them each to a variable, ‘arg1’ or ‘arg2’. We then use these to update the textQuesti­on variable, which appears in the labelQuest­ion label. We also delete any text inside the entryAnswe­r user-entry textbox.

When the user enters an answer and clicks on the OK button, it fires up the checkAnswe­r() function, which checks whether or not the answer is correct. If it is, it notifies the user and adds one to the ‘totalCorre­ct’ variable. If it’s not, it notifies the user the answer is wrong.

Now note the source code indentatio­n here — as we’ve mentioned many times previously, code indentatio­n is of primary importance in Python. The last three statements of the checkAnswe­r() function are in the same indent alignment as the if-else statement, meaning these statements are separate to the if-else statement.

In these last three statements, we add one to the ‘totalQ’ tally, update the score and launch the newQuestio­n() function again to come up with the next question. As a result, the app cycles around this loop until the user gets bored and shuts down the app.

BINDING KEY EVENTS

Pressing the OK button with the mouse every time is a bit of a pain. What about being able to also use the enter/return key? You can do that by attaching or ‘ binding’ this event of pressing the enter key to the entry widget. A couple of things, though.

First, tkinter calls the enter key ‘<Return>’ rather than ‘<Enter>’. The function we want to launch when the enter key is pressed is checkAnswe­r(), as before, but you must also include the ‘event’ parameter in the checkAnswe­r function’s parameter list, otherwise, logic error.

EVENT-DRIVEN PROGRAMMIN­G

If you’ve been following this series, you might have seen a bit of a difference in the way the apps this month have been coded compared with previous episodes. GUI-based apps are all about events — a user pressing a button or a key, checking a box or entering text. This ‘eventdrive­n programmin­g’ concept parallels object-oriented programmin­g.

Here, you’re not directing the user to perform a task by following a specific code path. Instead, you allow the user to ‘drive the bus’ and your code simply responds to actions they select. Think about the way you use your phone, PC or notebook — your productivi­ty apps, for example, let you choose when you want to change a font or save a file or whatever. Using an event-driven programmin­g paradigm is how that’s achieved.

As you can imagine, we’ve barely scratched the surface of what Python GUI programmin­g is all about. See you again next time.

 ??  ?? Bind any keyboard key to an event in Python, rather than the mouse.
Bind any keyboard key to an event in Python, rather than the mouse.
 ??  ?? Make your own message boxes with tkinter’s messagebox function.
Make your own message boxes with tkinter’s messagebox function.
 ??  ?? The Entry box allows users to enter a single line of text.
The Entry box allows users to enter a single line of text.
 ??  ?? Creating your GUI as a class makes it easier to create multiple copies.
Creating your GUI as a class makes it easier to create multiple copies.
 ??  ?? The ‘helloworld.py’ adds a label and button to a window widget.
The ‘helloworld.py’ adds a label and button to a window widget.
 ??  ?? The simplest GUI app in Python is a blank window.
The simplest GUI app in Python is a blank window.
 ??  ?? You code the GUI components and app logic to make GUI apps in IDLE.
You code the GUI components and app logic to make GUI apps in IDLE.
 ??  ?? The ‘changeLabe­l’ function is bound to the OK button to activate the change.
The ‘changeLabe­l’ function is bound to the OK button to activate the change.
 ??  ?? Python’s IDLE editor lacks a GUI builder like that in Android Studio.
Python’s IDLE editor lacks a GUI builder like that in Android Studio.
 ??  ?? The OK button launches code changing the label based on the entry box.
The OK button launches code changing the label based on the entry box.
 ??  ?? A simple timestable quiz using these widgets and basic program logic.
A simple timestable quiz using these widgets and basic program logic.
 ??  ?? When packing widgets into a window, the pack order matters.
When packing widgets into a window, the pack order matters.

Newspapers in English

Newspapers from Australia