Write a Graphical User Interface (GUI) program in Python which performs a simple mathematical feat. You can repeat the numerical problem in the P1 assignment, or create a new short mathematical problem, but here you will use a GUI.
Source code and images for all samples are here: src/
NOTE: You are creating one program, p2.py, with all the GUI options. It can be helpful to put in one option at a time, and run the program from IDLE after each change.
This is the best online reference available for Tkinter:
https://docs.python.org/3/library/tk.html
Python is often said to come with "batteries included". Compared to other languages, the standard Python installation includes much more, and enough to build interesting applications. Tkinter comes stock in most Python installations--and yours.
You are probably more used to GUI applications than anything else. When you start a GUI application, it waits for you to do something. This is an "event style" application, and events are button presses, text entries, click and drag a slider ... things like that.
The downside of GUI applications is that the code is lengthier, and it looks more complicated at first glance. Yet, it doesn't get much more complicated than what you see in this first program, and most items in a GUI can be copied and pasted along with a few minor modifications to get the kind of look and behavior needed.
The upsides of GUIs are high, though, so I decided it is a good idea to bring them in early. It is interesting to experiment with GUIs and tweak the appearance.
Your strategy with using Tkinter and writing GUIs should be the same as that used by experienced programmers. Hardly anyone can remember everything there is to know about GUIs, nor even Python. Experienced people use templates. Templates are working examples of code. Start with a template, in this case, with tk.py which you can copy to you own machine, open in the IDLE editor, and run. Here it is below:
Clicking on the link above should display tk.py as plain text in your browser window, and you can save it directly to your disk as a file, or you can copy the text from the browser and paste it within the IDLE editor then save it as tk.py or another file name ending with .py .
tk.py contains things which you will have in every Tkinter GUI, so we will look at it in detail. Here is the source code below (colors are for the discussion, not from IDLE editor syntax highlighting):
# simple Tkinter GUI - Wetherbee - January 18, 2023 # This program calculates the area of a rectangle. from tkinter import * # ------------------------------------------------------------- W = Tk() # create the window where everything is placed # create and place a quit button def quitter(): # our quit function to call by pressing B_quit W.destroy() sys.exit() B_quit = Button(W,text='Quit',command=quitter,bg="red") # create a button B_quit.grid(row=0,column=0) # place Button at 0,0 # entry for the length L1 = Label(W,text="Length") # create a Label L1.grid(row=1,column=0) # place label at 1,0 v1 = StringVar() # entry str variable E1 = Entry(W, textvariable=v1) # create an Entry box E1.grid(row=1,column=1) # place Entry at 1,1 # entry for the width L2 = Label(W,text="Width") # create a Label L2.grid(row=2,column=0) # place label at 2,0 v2 = StringVar() # entry str variable E2 = Entry(W, textvariable=v2) # create an Entry box E2.grid(row=2,column=1) # place Entry at 2,1 # entry for the area L3 = Label(W,text="Area") # create a Label L3.grid(row=3,column=0) # place label at 3,0 v3 = StringVar() # entry str variable E3 = Entry(W, textvariable=v3) # create an Entry box E3.grid(row=3,column=1) # place Entry at 3,1 # create and place a calculate button def calculate(): # our quit function to call by pressing B_quit length = float( v1.get() ) # get the length v1 in the E1 Entry box, convert to a float width = float( v2.get() ) # get the width v2 in the E2 Entry box, convert to a float area = length * width # calculate area v3.set( str(area) ) # place area value in the E3 Entry box using v3 B_calc = Button(W,text='Calc',command=calculate,bg="green") # create a button B_calc.grid(row=0,column=1) # place Button at 0,1 # -------------------------------------------------------------- mainloop() # hangs here forever, or until Quit button is pressed
If you run it from IDLE, the GUI starts and looks like this:
You might have to hunt for it because it is a tiny window which appears somewhere on your desktop. You must keep the IDLE windows open while tk.py is running. You enter numbers to the right of Length and Width. When the Calc button is pressed, the area is calculated (area = length*width) then displayed to the right of Area. To exit this GUI, click the Quit button.
Type numbers in the entry boxes after Length and Width, then press Calc to calculate the result--which should show up after Area. (You will see errors displayed in the IDLE interactive console if the Lentry boxes are blank or do not contain numbers.)
There are 8 widgets on this example: B_quit, L1, E1, L2, E2, L3, E3, B_calc. Each of these widgets is placed on the window W. This GUI code is almost entirely about defining each widget and placing each of them within the window W.
Your Tkinter GUI programs will always look something like this:
from tkinter import * # load Tkinter library W = Tk() # create the window W -- code for the GUI goes within here -- mainloop() # hangs here forever
from tkinter import *
W = Tk()
def quitter(): W.destroy() sys.exit()
B_quit = Button(W,text='Quit',command=quitter,bg="red")
B_quit.grid(row=0,column=0)
Here is how the grid placement looks.
There are 8 widgets to place on window W using grid: B_quit, L1, E1, L2, E2, L3, E3, B_calc. We simply decide where they should go, then define row and column by number to place it there using the .grid(row=__,column=__) command tasked onto the widget name. Note in the code that each of the 8 widgets is placed on the window W by using a row and column number.
L1 = Label(W,text="Length")
L1.grid(row=1,column=0)
v1 = StringVar()
E1 = Entry(W, textvariable=v1)
E1.grid(row=1,column=1)
Labels and entry boxes L2, E2, L3, and E3 are created almost identically as for L1 and E1, just labeled differently, using different variables, and placed in different locations.
def calculate(): length = float( v1.get() ) # get the length v1 in the E1 Entry box, convert to a float width = float( v2.get() ) # get the width v2 in the E2 Entry box, convert to a float area = length * width # calculate area v3.set( str(area) ) # place area value in the E3 Entry box using v3
B_calc = Button(W,text='Calc',command=calculate,bg="green")
B_calc.grid(row=0,column=1)
mainloop()
You can create padding around a widget by entering x and y padding values in pixels.
L1.grid(row=1,column=0,padx=10,pady=10)
Every widget (L1,L2,L3,E1,E2,E3,B_calc,B_quit) is modified with padx=10,pady=10 arguments when the widget is created, this making a 10 pixel pad around each in the x and y directions.
You can make a button larger with ipadx and ipady arguments.
B_quit.grid(row=0,column=0,ipadx=10,ipady=10)
The two buttons, B_calc and B_quit, are modified in this sample code.
You can make a color background for the window.
W.configure(bg="#CCCCFF")
The CC99FF is a red-green-blue hexadecimal number (base 16). The smallest possible value is 00, and the largest possible value is FF. CC=red, 99=green, and FF=blue in this "#CC99FF" color. You can also use well known color names like "green" and "red".
You can change the cursor when it appears over a button and some other widgets.
B_quit = Button(W,text='Quit',command=quitter,bg="red",cursor="gobbler")
A tcl/tk manual page shows many options: cursors
Use the name to the right of the cursor image. Above it is gobbler, a turkey which the cursor becomes when it is over the quit button.
You can place images in a window by putting an image into a Label instead of text. The image must be type .gif or .ppm, so likely .gif . You may have to experiment with sizes in pixels of the image, Width x Height in pixels.
L4_image = PhotoImage(file="logo.gif") L4 = Label(W,image=L4_image) L4.grid(row=4,column=0,columnspan=2)
The L4_image is the tkinter image, and logo.gif is the file name. The label L4 is create with the L4_image after the image is loaded, then the label is placed on the grid. Note the columnspan=2 argument which makes the label span column 0 and 1.
You can also put an image on a button instead of plain text. Here is the .gif image placed on the button.
B_calc = Button(W,command=calculate,bg="green") # create a button imageCalc = PhotoImage(file="calculate.gif") # load image B_calc.config(image=imageCalc) # put image on button B_calc.grid(row=0,column=1) # place Button at 0,1