Object oriented programming and particularly inheritance is commonly used for creating GUIs. There are a large number of different frameworks supporting building GUIs. The following are particularly relevant:
conda install pyqtgraph
In [37]:
import tkinter as tk
class Application(tk.Frame):
def __init__(self, master=None):
tk.Frame.__init__(self, master)
self.pack()
self.createWidgets()
def createWidgets(self):
self.hi_there = tk.Button(self)
self.hi_there["text"] = "Hello World\n(click me)"
self.hi_there["command"] = self.say_hi
self.hi_there.pack(side="top")
self.QUIT = tk.Button(self, text="QUIT", fg="red",
command=root.destroy)
self.QUIT.pack(side="bottom")
def say_hi(self):
print("hi there, everyone!")
root = tk.Tk()
app = Application(master=root)
app.mainloop()
Although this works, it is visually unappealing. We can improve on this using styles and themes.
In [48]:
import tkinter as tk
from tkinter import ttk
class Application(ttk.Frame):
def __init__(self, master=None):
super().__init__(master, padding="3 3 12 12")
self.grid(column=0, row=0, )
self.createWidgets()
self.master.title('Test')
def createWidgets(self):
self.hi_there = ttk.Button(self)
self.hi_there["text"] = "Hello World\n(click me)"
self.hi_there["command"] = self.say_hi
self.QUIT = ttk.Button(self, text="QUIT", style='Alert.TButton', command=root.destroy)
for child in self.winfo_children():
child.grid_configure(padx=10, pady=10)
def say_hi(self):
print("hi there, everyone!")
root = tk.Tk()
app = Application(master=root)
s = ttk.Style()
s.configure('TButton', font='helvetica 24')
s.configure('Alert.TButton', foreground='red')
root.mainloop()
As our applications get more complicated we must give greater thought to the layout. The following example comes from the TkDocs site.
In [28]:
from tkinter import *
from tkinter import ttk
def calculate(*args):
try:
value = float(feet.get())
meters.set((0.3048 * value * 10000.0 + 0.5)/10000.0)
except ValueError:
pass
root = Tk()
root.title("Feet to Meters")
mainframe = ttk.Frame(root, padding="3 3 12 12")
mainframe.grid(column=0, row=0, sticky=(N, W, E, S))
mainframe.columnconfigure(0, weight=1)
mainframe.rowconfigure(0, weight=1)
feet = StringVar()
meters = StringVar()
feet_entry = ttk.Entry(mainframe, width=7, textvariable=feet)
feet_entry.grid(column=2, row=1, sticky=(W, E))
ttk.Label(mainframe, textvariable=meters).grid(column=2, row=2, sticky=(W, E))
ttk.Button(mainframe, text="Calculate", command=calculate).grid(column=3, row=3, sticky=W)
ttk.Label(mainframe, text="feet").grid(column=3, row=1, sticky=W)
ttk.Label(mainframe, text="is equivalent to").grid(column=1, row=2, sticky=E)
ttk.Label(mainframe, text="meters").grid(column=3, row=2, sticky=W)
for child in mainframe.winfo_children(): child.grid_configure(padx=5, pady=5)
feet_entry.focus()
root.bind('<Return>', calculate)
root.mainloop()
For simple programs, displaying data and taking basic input, often a command line application will be much faster to implement than a GUI. The times when I have moved away from the command line it has been to interact with image data and plots. Here, matplotlib often works very well. Either it can be embedded in a larger application or it can be used directly.
There are a number of examples on the matplotlib site.
Here is one stripped down example of one recent GUI I have used.
In [ ]:
"""
Do a mouseclick somewhere, move the mouse to some destination, release
the button. This class gives click- and release-events and also draws
a line or a box from the click-point to the actual mouseposition
(within the same axes) until the button is released. Within the
method 'self.ignore()' it is checked wether the button from eventpress
and eventrelease are the same.
"""
from matplotlib.widgets import RectangleSelector
import matplotlib.pyplot as plt
import matplotlib.cbook as cbook
def line_select_callback(eclick, erelease):
'eclick and erelease are the press and release events'
x1, y1 = eclick.xdata, eclick.ydata
x2, y2 = erelease.xdata, erelease.ydata
print ("(%3.2f, %3.2f) --> (%3.2f, %3.2f)" % (x1, y1, x2, y2))
print (" The button you used were: %s %s" % (eclick.button, erelease.button))
def toggle_selector(event):
print (' Key pressed.')
if event.key in ['Q', 'q'] and toggle_selector.RS.active:
print (' RectangleSelector deactivated.')
toggle_selector.RS.set_active(False)
if event.key in ['A', 'a'] and not toggle_selector.RS.active:
print (' RectangleSelector activated.')
toggle_selector.RS.set_active(True)
image_file = cbook.get_sample_data('grace_hopper.png')
image = plt.imread(image_file)
fig, current_ax = plt.subplots()
plt.imshow(image)
toggle_selector.RS = RectangleSelector(current_ax,
line_select_callback,
drawtype='box', useblit=True,
button=[1,3], # don't use middle button
minspanx=5, minspany=5,
spancoords='pixels')
plt.connect('key_press_event', toggle_selector)
plt.show()
In [ ]: