Copyright(c) 2019
Author: Chaitanya Tejaswi (github.com/CRTejaswi) License: GPL v3.0+
Notes for Python3's Tkinter module.
-
Basic GUI
-
Widgets
- Types (17):
- Common Methods
- Specific Methods
-
Layout Management - grid, pack, place.
grid(row, column, rowspace, columnspace, padx, pady, ipadx, ipady, sticky)
pack(side, fill, expand)
-
Standard Attributes
-
Dialog Box - tkMessageBox, tkFileDialog, tkColorChooser.
- tkMessageBox: (.showinfo, .showwarning, .showerror),(.askokcancel, .askretrycancel, .askquestion, .askyesno).
- tkFileDialog: .askopenfilename, .asksaveasfilename.
- tkColorChooser: .askcolor.
-
Data Visualization: Canvas widget, Scipy stack.
-
Parallelization - Thread, Queue.
-
Internationalization
-
Testing
-
Cross-Platform Compatibility
-
Database Management
-
Packaging: setuptools, cx_Freeze.
-
Projects (Ideas)
- SlideShow: An image slideshow presenter.
- BlackJack: A single-player blackjack game.
- Form Fillup: A form-type bilingual data entry application.
- Text Editor: A customizable text-editor.
- Color Palette: A HEX-value chart for common RGB colors.
- Shows color tiles. Copies HEX value when the color tile is clicked.
- Enter HEX value to display corresponding style.
- Right click anywhere, choose
View color (RGB-HEX)
to get HEX values of that pixel.
- To-Do list.
- HEX Colors: Display color from HEX value. Suggests equivalent YCrCb, LSV, ... values.
- Image Viewer: Windows PhotoViewer Clone (JPG/PNG/GIF)
- Image-Grid: Grid-type (16:9) multiple image viewer.
- Image Visualizer: View chief properties of image; display like Image Viewer. User can scroll through images, and a PokeIndex type description for each image is provided. File Properties, Histogram, Features, Gradient,
- LogIn: Multi-User login system. Leads to a page contain the user's credentials (obtained during signup).
- Text Editor: Custom text-editor.
- Inventory Manager:
- Bill Generator: Template-based PDF bill generator.
- Chat Application:
- Audio Player:
- Video Player: Make a VLC-clone using Python & FFmpeg.
- Play local/remote videos.
- Adjust playback speed.
- Formulae Viewer: Generate mathematical formulae and look them up at your convenience.
- Use Latex fonts (
CMU
) for formulae. - Each formula can be copied as Latex code to be inserted elsewhere.
- Use Latex fonts (
- Graphing Calculator: Generate & visualize elementary math graphs.
- Use Latex fonts (
CMU
) for formulae. - Each graph/plot can be copied as Python code to be inserted elsewhere (with minimum modifications).
- Straight Lines, Conic Sections (circle, ellipse, parabola, hyperbola), Trigonometry (sin, cos, tan, cot, sec, cosec, ... ), Exponentials (log, ln, e), Statistics.
- Use Latex fonts (
-
Paradigms/Design Styles: imperative, object-oriented, asynchronous, functional.
-
Bibliography
- List/Access all variable types
.IntVar()
.DoubleVar()
.StringVar()
.BooleanVar()
import tkinter as tk
root = tk.Tk()
VARIABLES = [tk.IntVar(),
tk.DoubleVar(),
tk.StringVar(),
tk.BooleanVar()]
CONSTANTS = [2, 2.3, 'Hello World', True]
# Default Values
for index, value in enumerate(VARIABLES):
print(value.get())
value.set(CONSTANTS[index])
# Modified Values
for value in VARIABLES:
print(value.get())
0
0.0
False
2
2.3
Hello World
True
- Create an independent message box
from tkinter import messagebox as msg
root = tk.Tk()
root.withdraw()
msg.showinfo('Did You Know?', 'This GUI was created using Tkinter v8.6.')
# msg.showwarning('Warning!', 'Your details may be shared with 3rd Party Apps.')
# msg.showerror('Error!', 'Error: 404\n Page Not Found.')
- Insert Icons
root = tk.Tk()
img = tk.PhotoImage(file='resources/logos/summit.png')
root.tk.call('wm', 'iconphoto', window._w, img)
- Modify Fonts
FONT = ('System', 12, 'bold')
...
ttk.Label(window, text='LABEL', font=FONT).grid(row=0, column=0, sticky=tk.W)
- Open a webpage
import webbrowser
webbrowser.open('http://www.github/com/CRTejaswi')
- Focus on Entry/Tab
# Widget: Entry
input_name = ttk.Entry(window, width=20, textvariable=fname)
input_name.grid(row=0, column=1)
input_name.focus()
# Tab
tabs = ttk.Notebook(self.window)
...
tabN = ttk.Frame(tabs)
...
tabs.add(tabN, text='TabN')
tabs.pack(expand=1, fill='both')
tabs.select(tabN)
- tk & ttk Widgets
tk = tkinter .IntVar, .StringVar
ttk = themed tkinter(widgets) has 18 widgets
.Entry
.Label
.Frame
.LabelFrame
.Button
.Checkbutton
.Radiobutton
.Menubutton
.Scrollbar
.Progressbar
start()
step()
stop()
.Combobox
.Spinbox
.PanedWindow
.Notebook = create tabs -> https://docs.python.org/3/library/tkinter.ttk.html#tkinter.ttk.Notebook
add()
forget()
tab()
tabs()
select()
insert()
index()
enable_traversal()
.Separator
.Sizegrip
.Treeview
.Scale
- Alignment Options
.grid(row=x, column=y [, sticky=NSWE])
.pack()
.place(relx=x, rely=y [, anchor=CENTER])
- Basic GUI
v1
import tkinter as tk
from tkinter import ttk
window = tk.Tk()
window.title('Python GUI')
ttk.Label(window, text='Label#0').grid(row=0, column=0)
ttk.Label(window, text='Label#1').grid(row=1, column=1)
ttk.Label(window, text='Label#2').grid(row=2, column=2)
window.resizable(False, False)
window.mainloop()
v2.1
import tkinter as tk
from tkinter import ttk
window = tk.Tk()
window.title('Python GUI')
L0 = ttk.Label(window, text='Label#0')
L0.grid(row=0, column=0)
L1 = ttk.Label(window, text='Label#1')
L1.grid(row=1, column=1)
L2 = ttk.Label(window, text='Label#2')
L2.grid(row=2, column=2)
def red():
action.configure(text="Done!")
L0.configure(foreground='red', background='white')
L1.configure(foreground='red', background='white')
L2.configure(foreground='red', background='white')
def green():
action.configure(text="Done!")
L0.configure(foreground='green', background='white')
L1.configure(foreground='green', background='white')
L2.configure(foreground='green', background='white')
def blue():
action.configure(text="Done!")
L0.configure(foreground='blue', background='white')
L1.configure(foreground='blue', background='white')
L2.configure(foreground='blue', background='white')
action = ttk.Button(window, text='Red', command=red)
action.grid(row=3, column=0)
action = ttk.Button(window, text='Green', command=green)
action.grid(row=3, column=1)
action = ttk.Button(window, text='Blue', command=blue)
action.grid(row=3, column=2)
window.resizable(False, False)
window.mainloop()
v2.2
import tkinter as tk
from tkinter import ttk
window = tk.Tk()
window.title('Python GUI')
labels = []
labels.append(ttk.Label(window, text='Label#0'))
labels.append(ttk.Label(window, text='Label#1'))
labels.append(ttk.Label(window, text='Label#2'))
labels[0].grid(row=0, column=0)
labels[1].grid(row=1, column=1)
labels[2].grid(row=2, column=2)
def red():
for label in labels:
label.configure(foreground='red', background='white')
def green():
for label in labels:
label.configure(foreground='green', background='white')
def blue():
for label in labels:
label.configure(foreground='blue', background='white')
action = ttk.Button(window, text='Red', command=red)
action.grid(row=3, column=0)
action = ttk.Button(window, text='Green', command=green)
action.grid(row=3, column=1)
action = ttk.Button(window, text='Blue', command=blue)
action.grid(row=3, column=2)
window.resizable(False, False)
window.mainloop()
v2.3
import tkinter as tk
from tkinter import ttk
window = tk.Tk()
window.title('Python GUI')
# Create Labels
labels = []
label_name = 'Label#'
for i in range(3):
labels.append(ttk.Label(window, text=label_name + str(i + 1)))
for index, label in enumerate(labels):
label.grid(row=index, column=index)
# Event handlers for modifiying labels
def red():
for label in labels:
label.configure(foreground='red', background='white')
def green():
for label in labels:
label.configure(foreground='green', background='white')
def blue():
for label in labels:
label.configure(foreground='blue', background='white')
# Buttons for executing event handlers
action = ttk.Button(window, text='Red', command=red)
action.grid(row=3, column=0)
action = ttk.Button(window, text='Green', command=green)
action.grid(row=3, column=1)
action = ttk.Button(window, text='Blue', command=blue)
action.grid(row=3, column=2)
window.resizable(False, False)
window.mainloop()
- User Form
v1
import tkinter as tk
from tkinter import ttk
window = tk.Tk()
window.title('Python GUI')
# Create Labels
ttk.Label(window, text='Name: ').grid(row=0, column=0)
ttk.Label(window, text='Enrollment No.: ').grid(row=1, column=0)
ttk.Label(window, text='Password: ').grid(row=2, column=0)
name = tk.StringVar()
enrollment = tk.StringVar()
password = tk.StringVar()
input_name = ttk.Entry(window, width=20, textvariable=name)
input_enrollment = ttk.Entry(window, width=20, textvariable=enrollment)
input_password = ttk.Entry(window, width=20, textvariable=password)
input_name.grid(row=0, column=1)
input_enrollment.grid(row=1, column=1)
input_password.grid(row=2, column=1)
# Event handlers for modifiying labels
def ok():
action.configure(text='Welcome, {}!'.format(name.get()))
# Buttons for executing event handlers
action = ttk.Button(window, text='OK', command=ok)
action.grid(row=3, column=1)
input_name.focus()
window.resizable(False, False)
window.mainloop()
v2.1
CHANGES: Added DropDown options, removed Password.
import tkinter as tk
from tkinter import ttk
window = tk.Tk()
window.title('Python GUI')
# Create Labels
ttk.Label(window, text='First Name: ').grid(row=0, column=0)
fname = tk.StringVar()
ttk.Label(window, text='Last Name: ').grid(row=1, column=0)
lname = tk.StringVar()
ttk.Label(window, text='Enrollment No.: ').grid(row=2, column=0)
enrollment = tk.StringVar()
ttk.Label(window, text='Degree: ').grid(row=3, column=0)
degree = tk.StringVar()
ttk.Label(window, text='Department: ').grid(row=4, column=0)
department = tk.StringVar()
ttk.Label(window, text='Course: ').grid(row=5, column=0)
course = tk.StringVar()
input_fname = ttk.Entry(window, width=20, textvariable=fname)
input_lname = ttk.Entry(window, width=20, textvariable=lname)
input_enrollment = ttk.Entry(window, width=20, textvariable=enrollment)
input_degree = ttk.Combobox(window, width=30, textvariable=degree, state='readonly')
input_department = ttk.Combobox(window, width=30, textvariable=department, state='readonly')
input_course = ttk.Combobox(window, width=30, textvariable=course, state='readonly')
input_degree['values'] = ['BE/BTech', 'ME/MTech', 'BSc', 'MSc']
input_department['values'] = ('EE', 'ECE', 'CSE', 'Other')
input_course['values'] = ('C/C++ Data Structures & Algorithms',
'Python Data Structures & Algorithms',
'Electic Circuits: Design & Analysis',
'Electronic Circuits: Design & Analysis',
'Circuit Simulation & Design')
input_fname.grid(row=0, column=1)
input_lname.grid(row=1, column=1)
input_enrollment.grid(row=2, column=1)
input_degree.grid(row=3, column=1)
input_department.grid(row=4, column=1)
input_course.grid(row=5, column=1)
# Event handlers for modifiying labels
def ok():
action.configure(text='Welcome, {}!'.format(fname.get()))
# Buttons for executing event handlers
action = ttk.Button(window, text='OK', command=ok)
action.grid(row=6, column=1)
input_fname.focus()
# window.resizable(False, False)
window.mainloop()
v2.2
CHANGES: Added CheckBox (Disabled, Checked, Unchecked).
import tkinter as tk
from tkinter import ttk
window = tk.Tk()
window.title('Python GUI')
# Create Labels
ttk.Label(window, text='First Name: ').grid(row=0, column=0)
fname = tk.StringVar()
ttk.Label(window, text='Last Name: ').grid(row=1, column=0)
lname = tk.StringVar()
ttk.Label(window, text='Enrollment No.: ').grid(row=2, column=0)
enrollment = tk.StringVar()
ttk.Label(window, text='Degree: ').grid(row=3, column=0)
degree = tk.StringVar()
ttk.Label(window, text='Department: ').grid(row=4, column=0)
department = tk.StringVar()
ttk.Label(window, text='Course: ').grid(row=5, column=0)
course = tk.StringVar()
checkbox1 = tk.IntVar()
checkbox2 = tk.IntVar()
checkbox3 = tk.IntVar()
input_fname = ttk.Entry(window, width=20, textvariable=fname)
input_lname = ttk.Entry(window, width=20, textvariable=lname)
input_enrollment = ttk.Entry(window, width=20, textvariable=enrollment)
input_degree = ttk.Combobox(window, width=10, textvariable=degree, state='readonly')
input_department = ttk.Combobox(window, width=10, textvariable=department, state='readonly')
input_course = ttk.Combobox(window, width=30, textvariable=course, state='readonly')
input_degree['values'] = ['BE/BTech', 'ME/MTech', 'BSc', 'MSc']
input_department['values'] = ('EE', 'ECE', 'CSE', 'Other')
input_course['values'] = ('C/C++: Data Structures & Algorithms',
'Python: Data Structures & Algorithms',
'Electic Circuits: Design & Analysis',
'Electronic Circuits: Design & Analysis',
'Circuit Simulation & Design')
input_checkbox1 = tk.Checkbutton(window, text='Disabled', variable=checkbox1, state='disabled')
input_checkbox1.select()
input_checkbox2 = tk.Checkbutton(window, text='Checked', variable=checkbox2)
input_checkbox2.select()
input_checkbox3 = tk.Checkbutton(window, text='UnChecked', variable=checkbox3)
input_checkbox3.deselect()
input_fname.grid(row=0, column=1)
input_lname.grid(row=1, column=1)
input_enrollment.grid(row=2, column=1)
input_degree.grid(row=3, column=1)
input_department.grid(row=4, column=1)
input_course.grid(row=5, column=1)
input_checkbox1.grid(row=6, column=0)
input_checkbox2.grid(row=6, column=1)
input_checkbox3.grid(row=6, column=2)
# Event handlers for modifiying labels
def ok():
action.configure(text='Welcome, {}!'.format(fname.get()))
# Buttons for executing event handlers
action = ttk.Button(window, text='OK', command=ok)
action.grid(row=7, column=1)
input_fname.focus()
window.resizable(False, False)
window.mainloop()
v2.3
CHANGES: Added Radiobuttons that change the window's background.
import tkinter as tk
from tkinter import ttk
# Define Constants
COLOR1 = 'Red' # #FF0000
COLOR2 = 'Green' # #00FF00
COLOR3 = 'Blue' # #0000FF
window = tk.Tk()
window.title('Python GUI')
# Event handlers for modifiying labels
def ok():
action.configure(text='Welcome, {}!'.format(fname.get()))
def change_background():
choice = radiobtn.get()
if choice == 1:
window.configure(background=COLOR1)
elif choice == 2:
window.configure(background=COLOR2)
elif choice == 3:
window.configure(background=COLOR3)
# Create Labels
fname = tk.StringVar()
lname = tk.StringVar()
enrollment = tk.StringVar()
degree = tk.StringVar()
department = tk.StringVar()
course = tk.StringVar()
checkbox1 = tk.IntVar()
checkbox2 = tk.IntVar()
checkbox3 = tk.IntVar()
radiobtn = tk.IntVar()
ttk.Label(window, text='First Name: ').grid(row=0, column=0, sticky=tk.W)
ttk.Label(window, text='Last Name: ').grid(row=1, column=0, sticky=tk.W)
ttk.Label(window, text='Enrollment No.: ').grid(row=2, column=0, sticky=tk.W)
ttk.Label(window, text='Degree: ').grid(row=3, column=0, sticky=tk.W)
ttk.Label(window, text='Department: ').grid(row=4, column=0, sticky=tk.W)
ttk.Label(window, text='Course: ').grid(row=5, column=0, sticky=tk.W)
input_fname = ttk.Entry(window, width=20, textvariable=fname)
input_lname = ttk.Entry(window, width=20, textvariable=lname)
input_enrollment = ttk.Entry(window, width=20, textvariable=enrollment)
input_degree = ttk.Combobox(window, width=10, textvariable=degree, state='readonly')
input_department = ttk.Combobox(window, width=10, textvariable=department, state='readonly')
input_course = ttk.Combobox(window, width=30, textvariable=course, state='readonly')
input_degree['values'] = ['BE/BTech', 'ME/MTech', 'BSc', 'MSc']
input_department['values'] = ('EE', 'ECE', 'CSE', 'Other')
input_course['values'] = ('C/C++: Data Structures & Algorithms',
'Python: Data Structures & Algorithms',
'Electic Circuits: Design & Analysis',
'Electronic Circuits: Design & Analysis',
'Circuit Simulation & Design')
input_checkbox1 = tk.Checkbutton(window, text='Disabled', variable=checkbox1, state='disabled')
input_checkbox1.select()
input_checkbox2 = tk.Checkbutton(window, text='Checked', variable=checkbox2)
input_checkbox2.select()
input_checkbox3 = tk.Checkbutton(window, text='UnChecked', variable=checkbox3)
input_checkbox3.deselect()
input_radiobtn1 = tk.Radiobutton(window, text=COLOR1, variable=radiobtn, value=1, command=change_background)
input_radiobtn2 = tk.Radiobutton(window, text=COLOR2, variable=radiobtn, value=2, command=change_background)
input_radiobtn3 = tk.Radiobutton(window, text=COLOR3, variable=radiobtn, value=3, command=change_background)
input_fname.grid(row=0, column=1)
input_lname.grid(row=1, column=1)
input_enrollment.grid(row=2, column=1)
input_degree.grid(row=3, column=1)
input_department.grid(row=4, column=1)
input_course.grid(row=5, column=1)
input_checkbox1.grid(row=6, column=0)
input_checkbox2.grid(row=6, column=1)
input_checkbox3.grid(row=6, column=2)
input_radiobtn1.grid(row=7, column=0)
input_radiobtn2.grid(row=7, column=1)
input_radiobtn3.grid(row=7, column=2)
# Buttons for executing event handlers
action = ttk.Button(window, text='OK', command=ok)
action.grid(row=8, column=1)
input_fname.focus()
window.resizable(False, False)
window.mainloop()
v2.4
CHANGES: Added ScrollText which wraps words in a 5x50 space.
import tkinter as tk
from tkinter import ttk, scrolledtext
# Define Constants
COLOR1 = 'Red' # FF0000
COLOR2 = 'Green' # 00FF00
COLOR3 = 'Blue' # 0000FF
BIO_WIDTH = 50
BIO_HEIGHT = 5
window = tk.Tk()
window.title('Python GUI')
# Event handlers for modifiying labels
def ok():
action.configure(text='Welcome, {}!'.format(fname.get()))
def change_background():
choice = radiobtn.get()
if choice == 1:
window.configure(background=COLOR1)
elif choice == 2:
window.configure(background=COLOR2)
elif choice == 3:
window.configure(background=COLOR3)
# Create Labels
fname = tk.StringVar()
lname = tk.StringVar()
enrollment = tk.StringVar()
degree = tk.StringVar()
department = tk.StringVar()
course = tk.StringVar()
checkbox1 = tk.IntVar()
checkbox2 = tk.IntVar()
checkbox3 = tk.IntVar()
radiobtn = tk.IntVar()
ttk.Label(window, text='First Name: ').grid(row=0, column=0, sticky=tk.W)
ttk.Label(window, text='Last Name: ').grid(row=1, column=0, sticky=tk.W)
ttk.Label(window, text='Enrollment No.: ').grid(row=2, column=0, sticky=tk.W)
ttk.Label(window, text='Degree: ').grid(row=3, column=0, sticky=tk.W)
ttk.Label(window, text='Department: ').grid(row=4, column=0, sticky=tk.W)
ttk.Label(window, text='Course: ').grid(row=5, column=0, sticky=tk.W)
ttk.Label(window, text='Bio: ').grid(row=8, column=0, sticky=tk.W)
input_fname = ttk.Entry(window, width=20, textvariable=fname)
input_lname = ttk.Entry(window, width=20, textvariable=lname)
input_enrollment = ttk.Entry(window, width=20, textvariable=enrollment)
input_degree = ttk.Combobox(window, width=10, textvariable=degree, state='readonly')
input_department = ttk.Combobox(window, width=10, textvariable=department, state='readonly')
input_course = ttk.Combobox(window, width=30, textvariable=course, state='readonly')
input_degree['values'] = ['BE/BTech', 'ME/MTech', 'BSc', 'MSc']
input_department['values'] = ('EE', 'ECE', 'CSE', 'Other')
input_course['values'] = ('C/C++: Data Structures & Algorithms',
'Python: Data Structures & Algorithms',
'Electic Circuits: Design & Analysis',
'Electronic Circuits: Design & Analysis',
'Circuit Simulation & Design')
input_checkbox1 = tk.Checkbutton(window, text='Disabled', variable=checkbox1, state='disabled')
input_checkbox1.select()
input_checkbox2 = tk.Checkbutton(window, text='Checked', variable=checkbox2)
input_checkbox2.select()
input_checkbox3 = tk.Checkbutton(window, text='UnChecked', variable=checkbox3)
input_checkbox3.deselect()
input_radiobtn1 = tk.Radiobutton(window, text=COLOR1, variable=radiobtn, value=1, command=change_background)
input_radiobtn2 = tk.Radiobutton(window, text=COLOR2, variable=radiobtn, value=2, command=change_background)
input_radiobtn3 = tk.Radiobutton(window, text=COLOR3, variable=radiobtn, value=3, command=change_background)
input_bio = scrolledtext.ScrolledText(window, width=BIO_WIDTH, height=BIO_HEIGHT, wrap=tk.WORD)
input_fname.grid(row=0, column=1)
input_lname.grid(row=1, column=1)
input_enrollment.grid(row=2, column=1)
input_degree.grid(row=3, column=1)
input_department.grid(row=4, column=1)
input_course.grid(row=5, column=1)
input_checkbox1.grid(row=6, column=0)
input_checkbox2.grid(row=6, column=1)
input_checkbox3.grid(row=6, column=2)
input_radiobtn1.grid(row=7, column=0)
input_radiobtn2.grid(row=7, column=1)
input_radiobtn3.grid(row=7, column=2)
input_bio.grid(row=9, column=1)
# Buttons for executing event handlers
action = ttk.Button(window, text='OK', command=ok)
action.grid(row=10, column=1)
input_fname.focus()
window.resizable(False, False)
window.mainloop()
v2.5
CHANGES: Reduced v2.4.
import tkinter as tk
from tkinter import ttk, scrolledtext
# Define Constants
COLORS = ['Red', 'Green', 'Blue']
# COLORS = [#FF0000,#00FF00,#0000FF]
BIO_WIDTH = 50
BIO_HEIGHT = 5
window = tk.Tk()
window.title('Python GUI')
# Event handlers for modifiying labels
def ok():
action.configure(text='Welcome, {}!'.format(fname.get()))
def change_background():
choice = radiobtn.get()
if choice == 0:
window.configure(background=COLORS[0])
elif choice == 1:
window.configure(background=COLORS[1])
elif choice == 2:
window.configure(background=COLORS[2])
# Create Labels
fname = tk.StringVar()
lname = tk.StringVar()
enrollment = tk.StringVar()
degree = tk.StringVar()
department = tk.StringVar()
course = tk.StringVar()
checkbox1 = tk.IntVar()
checkbox2 = tk.IntVar()
checkbox3 = tk.IntVar()
radiobtn = tk.IntVar()
radiobtn.set(99)
ttk.Label(window, text='First Name: ').grid(row=0, column=0, sticky=tk.W)
ttk.Label(window, text='Last Name: ').grid(row=1, column=0, sticky=tk.W)
ttk.Label(window, text='Enrollment No.: ').grid(row=2, column=0, sticky=tk.W)
ttk.Label(window, text='Degree: ').grid(row=3, column=0, sticky=tk.W)
ttk.Label(window, text='Department: ').grid(row=4, column=0, sticky=tk.W)
ttk.Label(window, text='Course: ').grid(row=5, column=0, sticky=tk.W)
ttk.Label(window, text='Bio: ').grid(row=8, column=0, sticky=tk.W)
input_fname = ttk.Entry(window, width=20, textvariable=fname)
input_lname = ttk.Entry(window, width=20, textvariable=lname)
input_enrollment = ttk.Entry(window, width=20, textvariable=enrollment)
input_degree = ttk.Combobox(window, width=10, textvariable=degree, state='readonly')
input_department = ttk.Combobox(window, width=10, textvariable=department, state='readonly')
input_course = ttk.Combobox(window, width=30, textvariable=course, state='readonly')
input_degree['values'] = ['BE/BTech', 'ME/MTech', 'BSc', 'MSc']
input_department['values'] = ('EE', 'ECE', 'CSE', 'Other')
input_course['values'] = ('C/C++: Data Structures & Algorithms',
'Python: Data Structures & Algorithms',
'Electic Circuits: Design & Analysis',
'Electronic Circuits: Design & Analysis',
'Circuit Simulation & Design')
input_checkbox1 = tk.Checkbutton(window, text='Disabled', variable=checkbox1, state='disabled')
input_checkbox1.select()
input_checkbox2 = tk.Checkbutton(window, text='Checked', variable=checkbox2)
input_checkbox2.select()
input_checkbox3 = tk.Checkbutton(window, text='UnChecked', variable=checkbox3)
input_checkbox3.deselect()
for i in range(3):
input_radiobtn = tk.Radiobutton(window, text=COLORS[i], variable=radiobtn, value=i, command=change_background)
input_radiobtn.grid(row=7, column=i)
input_bio = scrolledtext.ScrolledText(window, width=BIO_WIDTH, height=BIO_HEIGHT, wrap=tk.WORD)
input_fname.grid(row=0, column=1)
input_lname.grid(row=1, column=1)
input_enrollment.grid(row=2, column=1)
input_degree.grid(row=3, column=1)
input_department.grid(row=4, column=1)
input_course.grid(row=5, column=1)
input_checkbox1.grid(row=6, column=0)
input_checkbox2.grid(row=6, column=1)
input_checkbox3.grid(row=6, column=2)
input_bio.grid(row=9, column=1)
# Buttons for executing event handlers
action = ttk.Button(window, text='OK', command=ok)
action.grid(row=10, column=1)
input_fname.focus()
window.resizable(False, False)
window.mainloop()
v2.6 [BROKEN]
CHANGES: Reduce v2.5.
import tkinter as tk
from tkinter import ttk, scrolledtext
# Define Constants
COLORS = ['Red', 'Green', 'Blue']
# COLORS = [#FF0000, #00FF00, #0000FF]
window = tk.Tk()
window.title('Python GUI')
# Event handlers for modifiying labels
def ok():
action.configure(text='Welcome, {}!'.format(fname.get()))
def change_background():
choice = radiobtn.get()
if choice == 0:
window.configure(background=COLORS[0])
elif choice == 1:
window.configure(background=COLORS[1])
elif choice == 2:
window.configure(background=COLORS[2])
# Define Variables
fname = tk.StringVar()
lname = tk.StringVar()
enrollment = tk.StringVar()
degree = tk.StringVar()
department = tk.StringVar()
course = tk.StringVar()
checkbox1 = tk.IntVar()
checkbox2 = tk.IntVar()
checkbox3 = tk.IntVar()
radiobtn = tk.IntVar()
radiobtn.set(99)
# Define Constants
HEADERS = ['First Name', 'Last Name: ', 'Enrollment No.: ', 'Degree: ', 'Department: ', 'Course: ', 'Bio: ']
LABELS = [fname, lname, enrollment, degree, department, course, bio]
VALUES = []
BIO_WIDTH = 50
BIO_HEIGHT = 5
# Define Labels & Widgets
for i in range(7):
ttk.Label(window, text=HEADERS[i]).grid(row=i, column=0, sticky=tk.W)
for i in range(12)
# Widget: Entry
while i < 3:
VALUES.append(ttk.Entry(window, width=20, textvariable=LABELS[i]))
VALUES[i].grid(row=i, column=1)
# Widget: ComboBox
while i >= 3 and i < 6:
VALUES.append(ttk.Combobox(window, width=30, textvariable=LABELS[i], state='readonly'))
VALUES[i].grid(row=i, column=1)
# Widget: ScrolledText
if i == 6:
VALUES.append(scrolledtext.ScrolledText(window, width=BIO_WIDTH, height=BIO_HEIGHT, wrap=tk.WORD))
VALUES[i].grid(row=i, column=1)
# Widget: RadioButton
if i == 7
for j in range(3):
VALUES.append(tk.Radiobutton(window, text=COLORS[i], variable=radiobtn, value=j, command=change_background))
VALUES[i].grid(row=i, column=j)
# Widget: CheckBox
if i == 8
for j in range(3):
VALUES.append(tk.Checkbutton(window, text='Checked', variable=checkbox2))
VALUES[i].grid(row=i, column=j)
input_bio =
input_checkbox1 = tk.Checkbutton(window, text='Disabled', variable=checkbox1, state='disabled')
input_checkbox1.select()
input_checkbox2 = tk.Checkbutton(window, text='Checked', variable=checkbox2)
input_checkbox2.select()
input_checkbox3 = tk.Checkbutton(window, text='UnChecked', variable=checkbox3)
input_checkbox3.deselect()
input_fname = ttk.Entry(window, width=20, textvariable=fname)
input_lname = ttk.Entry(window, width=20, textvariable=lname)
input_enrollment = ttk.Entry(window, width=20, textvariable=enrollment)
input_degree = ttk.Combobox(window, width=10, textvariable=degree, state='readonly')
input_department = ttk.Combobox(window, width=10, textvariable=department, state='readonly')
input_course = ttk.Combobox(window, width=30, textvariable=course, state='readonly')
input_degree['values'] = ['BE/BTech', 'ME/MTech', 'BSc', 'MSc']
input_department['values'] = ('EE', 'ECE', 'CSE', 'Other')
input_course['values'] = ('C/C++: Data Structures & Algorithms',
'Python: Data Structures & Algorithms',
'Electic Circuits: Design & Analysis',
'Electronic Circuits: Design & Analysis',
'Circuit Simulation & Design')
input_fname.grid(row=0, column=1)
input_lname.grid(row=1, column=1)
input_enrollment.grid(row=2, column=1)
input_degree.grid(row=3, column=1)
input_department.grid(row=4, column=1)
input_course.grid(row=5, column=1)
input_checkbox1.grid(row=6, column=0)
input_checkbox2.grid(row=6, column=1)
input_checkbox3.grid(row=6, column=2)
input_bio.grid(row=9, column=1)
# Buttons for executing event handlers
action = ttk.Button(window, text='OK', command=ok)
action.grid(row=10, column=1)
input_fname.focus()
window.resizable(False, False)
window.mainloop()
v2.7
CHANGES: Added Font-Formatting for labels. Experimenting with ButtonFrame.
import tkinter as tk
from tkinter import ttk, scrolledtext
# Define Constants
COLORS = ['Red', 'Green', 'Blue']
# COLORS = [#FF0000,#00FF00,#0000FF]
BIO_WIDTH = 50
BIO_HEIGHT = 5
FONT = ('System', 12, 'bold')
window = tk.Tk()
window.title('Python GUI')
# Event handlers for modifiying labels
def ok():
action.configure(text='Welcome, {}!'.format(fname.get()))
def change_background():
choice = radiobtn.get()
if choice == 0:
window.configure(background=COLORS[0])
elif choice == 1:
window.configure(background=COLORS[1])
elif choice == 2:
window.configure(background=COLORS[2])
# Create Labels
fname = tk.StringVar()
lname = tk.StringVar()
enrollment = tk.StringVar()
degree = tk.StringVar()
department = tk.StringVar()
course = tk.StringVar()
checkbox1 = tk.IntVar()
checkbox2 = tk.IntVar()
checkbox3 = tk.IntVar()
radiobtn = tk.IntVar()
radiobtn.set(99)
ttk.Label(window, text='First Name: ', font=FONT).grid(row=0, column=0, sticky=tk.W)
ttk.Label(window, text='Last Name: ', font=FONT).grid(row=1, column=0, sticky=tk.W)
ttk.Label(window, text='Enrollment No.: ', font=FONT).grid(row=2, column=0, sticky=tk.W)
ttk.Label(window, text='Degree: ', font=FONT).grid(row=3, column=0, sticky=tk.W)
ttk.Label(window, text='Department: ', font=FONT).grid(row=4, column=0, sticky=tk.W)
ttk.Label(window, text='Course: ', font=FONT).grid(row=5, column=0, sticky=tk.W)
ttk.Label(window, text='Bio: ', font=FONT).grid(row=8, column=0, sticky=tk.W)
input_fname = ttk.Entry(window, width=20, textvariable=fname)
input_lname = ttk.Entry(window, width=20, textvariable=lname)
input_enrollment = ttk.Entry(window, width=20, textvariable=enrollment)
input_degree = ttk.Combobox(window, width=10, textvariable=degree, state='readonly')
input_department = ttk.Combobox(window, width=10, textvariable=department, state='readonly')
input_course = ttk.Combobox(window, width=30, textvariable=course, state='readonly')
input_degree['values'] = ['BE/BTech', 'ME/MTech', 'BSc', 'MSc']
input_department['values'] = ('EE', 'ECE', 'CSE', 'Other')
input_course['values'] = ('C/C++: Data Structures & Algorithms',
'Python: Data Structures & Algorithms',
'Electic Circuits: Design & Analysis',
'Electronic Circuits: Design & Analysis',
'Circuit Simulation & Design')
input_checkbox1 = tk.Checkbutton(window, text='Disabled', variable=checkbox1, state='disabled')
input_checkbox1.select()
input_checkbox2 = tk.Checkbutton(window, text='Checked', variable=checkbox2)
input_checkbox2.select()
input_checkbox3 = tk.Checkbutton(window, text='UnChecked', variable=checkbox3)
input_checkbox3.deselect()
for i in range(3):
input_radiobtn = tk.Radiobutton(window, text=COLORS[i], variable=radiobtn, value=i, command=change_background)
input_radiobtn.grid(row=7, column=i)
input_bio = scrolledtext.ScrolledText(window, width=BIO_WIDTH, height=BIO_HEIGHT, wrap=tk.WORD)
input_fname.grid(row=0, column=1)
input_lname.grid(row=1, column=1)
input_enrollment.grid(row=2, column=1)
input_degree.grid(row=3, column=1)
input_department.grid(row=4, column=1)
input_course.grid(row=5, column=1)
input_checkbox1.grid(row=6, column=0)
input_checkbox2.grid(row=6, column=1)
input_checkbox3.grid(row=6, column=2)
input_bio.grid(row=9, column=0, columnspan=3)
# Buttons for executing event handlers
action = ttk.Button(window, text='OK', command=ok)
action.grid(row=10, column=1)
# ButtonFrame labels
buttonframe = ttk.LabelFrame(window, text='Labels Within A Frame')
buttonframe.grid(row=11, column=0, padx=20, pady=20)
# Horizontal Alignment
ttk.Label(buttonframe, text='X1').grid(row=0, column=1)
ttk.Label(buttonframe, text='X2').grid(row=0, column=2)
ttk.Label(buttonframe, text='X3').grid(row=0, column=3)
# Vertical Alignment
ttk.Label(buttonframe, text='Y1').grid(row=1, column=0)
ttk.Label(buttonframe, text='Y2').grid(row=2, column=0)
ttk.Label(buttonframe, text='Y3').grid(row=3, column=0)
for child in buttonframe.winfo_children():
child.grid_configure(padx=5, pady=5)
input_fname.focus()
window.resizable(False, False)
window.mainloop()
v2.8
CHANGES: Experimenting with LabelFrame.
import tkinter as tk
from tkinter import ttk, scrolledtext
# Define Constants
COLORS = ['Red', 'Green', 'Blue']
# COLORS = [#FF0000,#00FF00,#0000FF]
BIO_WIDTH = 50
BIO_HEIGHT = 5
FONT = ('System', 12, 'bold')
window = tk.Tk()
window.title('Python GUI')
widget = ttk.LabelFrame(window, text='Widget LabelFrame')
widget.grid(row=0, column=0, padx=10, pady=10)
# Event handlers for modifiying labels
def ok():
action.configure(text='Welcome, {}!'.format(fname.get()))
def change_background():
choice = radiobtn.get()
if choice == 0:
window.configure(background=COLORS[0])
elif choice == 1:
window.configure(background=COLORS[1])
elif choice == 2:
window.configure(background=COLORS[2])
# Create Labels
fname = tk.StringVar()
lname = tk.StringVar()
enrollment = tk.StringVar()
degree = tk.StringVar()
department = tk.StringVar()
course = tk.StringVar()
checkbox1 = tk.IntVar()
checkbox2 = tk.IntVar()
checkbox3 = tk.IntVar()
radiobtn = tk.IntVar()
radiobtn.set(99)
ttk.Label(widget, text='First Name: ', font=FONT).grid(row=0, column=0, sticky=tk.W)
ttk.Label(widget, text='Last Name: ', font=FONT).grid(row=1, column=0, sticky=tk.W)
ttk.Label(widget, text='Enrollment No.: ', font=FONT).grid(row=2, column=0, sticky=tk.W)
ttk.Label(widget, text='Degree: ', font=FONT).grid(row=3, column=0, sticky=tk.W)
ttk.Label(widget, text='Department: ', font=FONT).grid(row=4, column=0, sticky=tk.W)
ttk.Label(widget, text='Course: ', font=FONT).grid(row=5, column=0, sticky=tk.W)
ttk.Label(widget, text='Bio: ', font=FONT).grid(row=8, column=0, sticky=tk.W)
input_fname = ttk.Entry(widget, width=20, textvariable=fname)
input_lname = ttk.Entry(widget, width=20, textvariable=lname)
input_enrollment = ttk.Entry(widget, width=20, textvariable=enrollment)
input_degree = ttk.Combobox(widget, width=10, textvariable=degree, state='readonly')
input_department = ttk.Combobox(widget, width=10, textvariable=department, state='readonly')
input_course = ttk.Combobox(widget, width=30, textvariable=course, state='readonly')
input_degree['values'] = ['BE/BTech', 'ME/MTech', 'BSc', 'MSc']
input_department['values'] = ('EE', 'ECE', 'CSE', 'Other')
input_course['values'] = ('C/C++: Data Structures & Algorithms',
'Python: Data Structures & Algorithms',
'Electic Circuits: Design & Analysis',
'Electronic Circuits: Design & Analysis',
'Circuit Simulation & Design')
input_checkbox1 = tk.Checkbutton(widget, text='Disabled', variable=checkbox1, state='disabled')
input_checkbox1.select()
input_checkbox2 = tk.Checkbutton(widget, text='Checked', variable=checkbox2)
input_checkbox2.select()
input_checkbox3 = tk.Checkbutton(widget, text='UnChecked', variable=checkbox3)
input_checkbox3.deselect()
for i in range(3):
input_radiobtn = tk.Radiobutton(widget, text=COLORS[i], variable=radiobtn, value=i, command=change_background)
input_radiobtn.grid(row=7, column=i)
input_bio = scrolledtext.ScrolledText(widget, width=BIO_WIDTH, height=BIO_HEIGHT, wrap=tk.WORD)
input_fname.grid(row=0, column=1)
input_lname.grid(row=1, column=1)
input_enrollment.grid(row=2, column=1)
input_degree.grid(row=3, column=1)
input_department.grid(row=4, column=1)
input_course.grid(row=5, column=1)
input_checkbox1.grid(row=6, column=0)
input_checkbox2.grid(row=6, column=1)
input_checkbox3.grid(row=6, column=2)
input_bio.grid(row=9, column=0, columnspan=3)
# Buttons for executing event handlers
action = ttk.Button(widget, text='OK', command=ok)
action.grid(row=10, column=1)
# ButtonFrame labels
buttonframe = ttk.LabelFrame(widget, text='Labels Within A Frame')
buttonframe.grid(row=11, column=0, padx=20, pady=20)
# Horizontal Alignment
ttk.Label(buttonframe, text='X1').grid(row=0, column=1)
ttk.Label(buttonframe, text='X2').grid(row=0, column=2)
ttk.Label(buttonframe, text='X3').grid(row=0, column=3)
# Vertical Alignment
ttk.Label(buttonframe, text='Y1').grid(row=1, column=0)
ttk.Label(buttonframe, text='Y2').grid(row=2, column=0)
ttk.Label(buttonframe, text='Y3').grid(row=3, column=0)
for child in buttonframe.winfo_children():
child.grid_configure(padx=5, pady=5)
input_fname.focus()
window.resizable(False, False)
window.mainloop()
v2.9
CHANGES: Added Menubars.
import tkinter as tk
from tkinter import ttk, scrolledtext, Menu
# Define Constants
COLORS = ['Red', 'Green', 'Blue']
# COLORS = [#FF0000,#00FF00,#0000FF]
BIO_WIDTH = 50
BIO_HEIGHT = 5
FONT = ('System', 12, 'bold')
window = tk.Tk()
window.title('Python GUI')
widget = ttk.LabelFrame(window, text='Widget LabelFrame')
widget.grid(row=0, column=0, padx=10, pady=10)
menubar = Menu(window)
window.configure(menu=menubar)
# Event handlers for modifiying labels
def ok():
action.configure(text='Welcome, {}!'.format(fname.get()))
def change_background():
choice = radiobtn.get()
if choice == 0:
window.configure(background=COLORS[0])
elif choice == 1:
window.configure(background=COLORS[1])
elif choice == 2:
window.configure(background=COLORS[2])
def _quit():
window.quit()
window.destroy()
exit()
# Create Menus
menu_file = Menu(menubar, tearoff=0)
menu_edit = Menu(menubar, tearoff=0)
menu_view = Menu(menubar, tearoff=0)
menu_help = Menu(menubar, tearoff=0)
menu_file.add_command(label='New')
menu_file.add_command(label='Open')
menu_file.add_command(label='Close')
menu_file.add_command(label='Quit', command=_quit)
menu_file.add_command(label='Save')
menu_file.add_command(label='Save As')
menu_file.add_command(label='Print')
menubar.add_cascade(label='File', menu=menu_file)
menu_edit.add_command(label='Cut')
menu_edit.add_command(label='Copy')
menu_edit.add_command(label='Paste')
menu_edit.add_command(label='Find')
menu_edit.add_command(label='Replace')
menubar.add_cascade(label='Edit', menu=menu_edit)
menu_view.add_command(label='Status Bar')
menubar.add_cascade(label='View', menu=menu_view)
menu_help.add_command(label='About')
menubar.add_cascade(label='Help', menu=menu_help)
# Create Labels
fname = tk.StringVar()
lname = tk.StringVar()
enrollment = tk.StringVar()
degree = tk.StringVar()
department = tk.StringVar()
course = tk.StringVar()
checkbox1 = tk.IntVar()
checkbox2 = tk.IntVar()
checkbox3 = tk.IntVar()
radiobtn = tk.IntVar()
radiobtn.set(99)
ttk.Label(widget, text='First Name: ', font=FONT).grid(row=0, column=0, sticky=tk.W)
ttk.Label(widget, text='Last Name: ', font=FONT).grid(row=1, column=0, sticky=tk.W)
ttk.Label(widget, text='Enrollment No.: ', font=FONT).grid(row=2, column=0, sticky=tk.W)
ttk.Label(widget, text='Degree: ', font=FONT).grid(row=3, column=0, sticky=tk.W)
ttk.Label(widget, text='Department: ', font=FONT).grid(row=4, column=0, sticky=tk.W)
ttk.Label(widget, text='Course: ', font=FONT).grid(row=5, column=0, sticky=tk.W)
ttk.Label(widget, text='Bio: ', font=FONT).grid(row=8, column=0, sticky=tk.W)
input_fname = ttk.Entry(widget, width=20, textvariable=fname)
input_lname = ttk.Entry(widget, width=20, textvariable=lname)
input_enrollment = ttk.Entry(widget, width=20, textvariable=enrollment)
input_degree = ttk.Combobox(widget, width=10, textvariable=degree, state='readonly')
input_department = ttk.Combobox(widget, width=10, textvariable=department, state='readonly')
input_course = ttk.Combobox(widget, width=30, textvariable=course, state='readonly')
input_degree['values'] = ['BE/BTech', 'ME/MTech', 'BSc', 'MSc']
input_department['values'] = ('EE', 'ECE', 'CSE', 'Other')
input_course['values'] = ('C/C++: Data Structures & Algorithms',
'Python: Data Structures & Algorithms',
'Electic Circuits: Design & Analysis',
'Electronic Circuits: Design & Analysis',
'Circuit Simulation & Design')
input_checkbox1 = tk.Checkbutton(widget, text='Disabled', variable=checkbox1, state='disabled')
input_checkbox1.select()
input_checkbox2 = tk.Checkbutton(widget, text='Checked', variable=checkbox2)
input_checkbox2.select()
input_checkbox3 = tk.Checkbutton(widget, text='UnChecked', variable=checkbox3)
input_checkbox3.deselect()
for i in range(3):
input_radiobtn = tk.Radiobutton(widget, text=COLORS[i], variable=radiobtn, value=i, command=change_background)
input_radiobtn.grid(row=7, column=i)
input_bio = scrolledtext.ScrolledText(widget, width=BIO_WIDTH, height=BIO_HEIGHT, wrap=tk.WORD)
input_fname.grid(row=0, column=1)
input_lname.grid(row=1, column=1)
input_enrollment.grid(row=2, column=1)
input_degree.grid(row=3, column=1)
input_department.grid(row=4, column=1)
input_course.grid(row=5, column=1)
input_checkbox1.grid(row=6, column=0)
input_checkbox2.grid(row=6, column=1)
input_checkbox3.grid(row=6, column=2)
input_bio.grid(row=9, column=0, columnspan=3)
# Buttons for executing event handlers
action = ttk.Button(widget, text='OK', command=ok)
action.grid(row=10, column=1)
# ButtonFrame labels
buttonframe = ttk.LabelFrame(widget, text='Labels Within A Frame')
buttonframe.grid(row=11, column=0, padx=20, pady=20)
# Horizontal Alignment
ttk.Label(buttonframe, text='X1').grid(row=0, column=1)
ttk.Label(buttonframe, text='X2').grid(row=0, column=2)
ttk.Label(buttonframe, text='X3').grid(row=0, column=3)
# Vertical Alignment
ttk.Label(buttonframe, text='Y1').grid(row=1, column=0)
ttk.Label(buttonframe, text='Y2').grid(row=2, column=0)
ttk.Label(buttonframe, text='Y3').grid(row=3, column=0)
for child in buttonframe.winfo_children():
child.grid_configure(padx=5, pady=5)
input_fname.focus()
window.resizable(False, False)
window.mainloop()
v2.A
CHANGES: Added Tabs. (change_background() doesn't work.)
import tkinter as tk
from tkinter import ttk, scrolledtext, Menu
# Define Constants
COLORS = ['Red', 'Green', 'Blue']
# COLORS = [#FF0000,#00FF00,#0000FF]
BIO_WIDTH = 50
BIO_HEIGHT = 5
FONT = ('System', 12, 'bold')
window = tk.Tk()
window.title('Python GUI')
menubar = Menu(window)
window.configure(menu=menubar)
tabs = ttk.Notebook(window)
# Create Tabs
tab1 = ttk.Frame(tabs)
tab2 = ttk.Frame(tabs)
tab3 = ttk.Frame(tabs)
tabs.add(tab1, text='Tab1')
tabs.add(tab2, text='Tab2')
tabs.add(tab3, text='Tab3')
tabs.pack(expand=1, fill='both')
# Create widgets within tabs
# Tab: 1
widget1 = ttk.LabelFrame(tab1, text='LabelFrame')
widget1.grid(row=0, column=0, padx=10, pady=10)
# Tab: 2
widget2 = ttk.LabelFrame(tab2, text='LabelFrame')
widget2.grid(row=0, column=0, padx=10, pady=10)
# Tab: 3
widget3 = ttk.LabelFrame(tab3, text='LabelFrame')
widget3.grid(row=0, column=0, padx=10, pady=10)
# Event handlers for modifiying labels
def ok():
action.configure(text='Welcome, {}!'.format(fname.get()))
def change_background():
choice = radiobtn.get()
if choice == 0:
window.configure(background=COLORS[0])
elif choice == 1:
window.configure(background=COLORS[1])
elif choice == 2:
window.configure(background=COLORS[2])
def _quit():
window.quit()
window.destroy()
exit()
# Create Menus
menu_file = Menu(menubar, tearoff=0)
menu_edit = Menu(menubar, tearoff=0)
menu_view = Menu(menubar, tearoff=0)
menu_help = Menu(menubar, tearoff=0)
menu_file.add_command(label='New')
menu_file.add_command(label='Open')
menu_file.add_command(label='Close')
menu_file.add_command(label='Quit', command=_quit)
menu_file.add_command(label='Save')
menu_file.add_command(label='Save As')
menu_file.add_command(label='Print')
menubar.add_cascade(label='File', menu=menu_file)
menu_edit.add_command(label='Cut')
menu_edit.add_command(label='Copy')
menu_edit.add_command(label='Paste')
menu_edit.add_command(label='Find')
menu_edit.add_command(label='Replace')
menubar.add_cascade(label='Edit', menu=menu_edit)
menu_view.add_command(label='Status Bar')
menubar.add_cascade(label='View', menu=menu_view)
menu_help.add_command(label='About')
menubar.add_cascade(label='Help', menu=menu_help)
# Tab1: Widgets
# Create Labels
fname = tk.StringVar()
lname = tk.StringVar()
enrollment = tk.StringVar()
degree = tk.StringVar()
department = tk.StringVar()
course = tk.StringVar()
checkbox1 = tk.IntVar()
checkbox2 = tk.IntVar()
checkbox3 = tk.IntVar()
radiobtn = tk.IntVar()
radiobtn.set(99)
ttk.Label(widget1, text='First Name: ', font=FONT).grid(row=0, column=0, sticky=tk.W)
ttk.Label(widget1, text='Last Name: ', font=FONT).grid(row=1, column=0, sticky=tk.W)
ttk.Label(widget1, text='Enrollment No.: ', font=FONT).grid(row=2, column=0, sticky=tk.W)
ttk.Label(widget1, text='Degree: ', font=FONT).grid(row=3, column=0, sticky=tk.W)
ttk.Label(widget1, text='Department: ', font=FONT).grid(row=4, column=0, sticky=tk.W)
ttk.Label(widget1, text='Course: ', font=FONT).grid(row=5, column=0, sticky=tk.W)
ttk.Label(widget1, text='Bio: ', font=FONT).grid(row=6, column=0, sticky=tk.W)
# Create Elements
input_fname = ttk.Entry(widget1, width=20, textvariable=fname)
input_lname = ttk.Entry(widget1, width=20, textvariable=lname)
input_enrollment = ttk.Entry(widget1, width=20, textvariable=enrollment)
input_degree = ttk.Combobox(widget1, width=10, textvariable=degree, state='readonly')
input_department = ttk.Combobox(widget1, width=10, textvariable=department, state='readonly')
input_course = ttk.Combobox(widget1, width=30, textvariable=course, state='readonly')
input_degree['values'] = ['BE/BTech', 'ME/MTech', 'BSc', 'MSc']
input_department['values'] = ('EE', 'ECE', 'CSE', 'Other')
input_course['values'] = ('C/C++: Data Structures & Algorithms',
'Python: Data Structures & Algorithms',
'Electic Circuits: Design & Analysis',
'Electronic Circuits: Design & Analysis',
'Circuit Simulation & Design')
input_bio = scrolledtext.ScrolledText(widget1, width=BIO_WIDTH, height=BIO_HEIGHT, wrap=tk.WORD)
input_fname.grid(row=0, column=1)
input_lname.grid(row=1, column=1)
input_enrollment.grid(row=2, column=1)
input_degree.grid(row=3, column=1)
input_department.grid(row=4, column=1)
input_course.grid(row=5, column=1)
input_bio.grid(row=7, column=0, columnspan=3)
# Buttons for executing event handlers
action = ttk.Button(widget1, text='OK', command=ok)
action.grid(row=8, column=0, anchor=CENTER)
# Tab2: Widgets
# Create Elements
input_checkbox1 = tk.Checkbutton(widget2, text='Disabled', variable=checkbox1, state='disabled')
input_checkbox1.select()
input_checkbox2 = tk.Checkbutton(widget2, text='Checked', variable=checkbox2)
input_checkbox2.select()
input_checkbox3 = tk.Checkbutton(widget2, text='UnChecked', variable=checkbox3)
input_checkbox3.deselect()
input_checkbox1.grid(row=1, column=0)
input_checkbox2.grid(row=1, column=1)
input_checkbox3.grid(row=1, column=2)
# Tab3: Widgets
# Create Elements
buttonframe = ttk.LabelFrame(widget3, text='Labels Within A Frame')
buttonframe.grid(row=11, column=0, padx=20, pady=20)
# Horizontal Alignment
ttk.Label(buttonframe, text='X1').grid(row=0, column=1)
ttk.Label(buttonframe, text='X2').grid(row=0, column=2)
ttk.Label(buttonframe, text='X3').grid(row=0, column=3)
# Vertical Alignment
ttk.Label(buttonframe, text='Y1').grid(row=1, column=0)
ttk.Label(buttonframe, text='Y2').grid(row=2, column=0)
ttk.Label(buttonframe, text='Y3').grid(row=3, column=0)
for child in buttonframe.winfo_children():
child.grid_configure(padx=5, pady=5)
for i in range(3):
input_radiobtn = tk.Radiobutton(widget3, text=COLORS[i], variable=radiobtn, value=i, command=change_background)
input_radiobtn.grid(row=9, column=i)
input_fname.focus()
window.resizable(False, False)
window.mainloop()
- Creating message boxes – information, warning, and error
- How to create independent message boxes
- How to create the title of a tkinter window form
- Changing the icon of the main root window
- Using a spin box control
- Relief, sunken, and raised appearance of widgets
- Creating tooltips using Python
- Adding a progressbar to the GUI
- How to use the canvas widget
v2.B
CHANGES:
Added message boxes (info, warning, error, yes-no-cancel) & root-window logo.
About
opens up a webpage.
import tkinter as tk
from tkinter import ttk, scrolledtext, Menu, messagebox as msg
import webbrowser
# Define Constants
COLORS = ['Red', 'Green', 'Blue']
# COLORS = [#FF0000,#00FF00,#0000FF]
BIO_WIDTH = 50
BIO_HEIGHT = 5
FONT = ('System', 12, 'bold')
window = tk.Tk()
window.title('Python GUI')
menubar = Menu(window)
window.configure(menu=menubar)
tabs = ttk.Notebook(window)
# Set PNG image as root logo
img = tk.PhotoImage(file='resources/logos/summit.png')
window.tk.call('wm', 'iconphoto', window._w, img)
# Create Tabs
tab1 = ttk.Frame(tabs)
tab2 = ttk.Frame(tabs)
tab3 = ttk.Frame(tabs)
tabs.add(tab1, text='Tab1')
tabs.add(tab2, text='Tab2')
tabs.add(tab3, text='Tab3')
tabs.pack(expand=1, fill='both')
# Create widgets within tabs
# Tab: 1
widget1 = ttk.LabelFrame(tab1, text='LabelFrame')
widget1.grid(row=0, column=0, padx=10, pady=10)
# Tab: 2
widget2 = ttk.LabelFrame(tab2, text='LabelFrame')
widget2.grid(row=0, column=0, padx=10, pady=10)
# Tab: 3
widget3 = ttk.LabelFrame(tab3, text='LabelFrame')
widget3.grid(row=0, column=0, padx=10, pady=10)
# Event handlers for modifiying labels
def ok():
action.configure(text='Welcome, {}!'.format(fname.get()))
def change_background():
choice = radiobtn.get()
if choice == 0:
window.configure(background=COLORS[0])
elif choice == 1:
window.configure(background=COLORS[1])
elif choice == 2:
window.configure(background=COLORS[2])
def _quit():
window.quit()
window.destroy()
exit()
def _msgbox():
# msg.showinfo('Did You Know?', 'This GUI was created using Tkinter v8.6.')
# msg.showwarning('Warning!', 'Your details may be shared with 3rd Party Apps.')
# msg.showerror('Error!', 'Error: 404\n Page Not Found.')
answer = msg.askyesnocancel('GUI Information', 'Do you want to know more?')
if answer == True:
webbrowser.open('http://www.github.com/CRTejaswi')
# Create Menus
menu_file = Menu(menubar, tearoff=0)
menu_edit = Menu(menubar, tearoff=0)
menu_view = Menu(menubar, tearoff=0)
menu_help = Menu(menubar, tearoff=0)
menu_file.add_command(label='New')
menu_file.add_command(label='Open')
menu_file.add_command(label='Close')
menu_file.add_command(label='Quit', command=_quit)
menu_file.add_command(label='Save')
menu_file.add_command(label='Save As')
menu_file.add_command(label='Print')
menubar.add_cascade(label='File', menu=menu_file)
menu_edit.add_command(label='Cut')
menu_edit.add_command(label='Copy')
menu_edit.add_command(label='Paste')
menu_edit.add_command(label='Find')
menu_edit.add_command(label='Replace')
menubar.add_cascade(label='Edit', menu=menu_edit)
menu_view.add_command(label='Status Bar')
menubar.add_cascade(label='View', menu=menu_view)
menu_help.add_command(label='About', command=_msgbox)
menubar.add_cascade(label='Help', menu=menu_help)
# Tab1: Widgets
# Create Labels
fname = tk.StringVar()
lname = tk.StringVar()
enrollment = tk.StringVar()
degree = tk.StringVar()
department = tk.StringVar()
course = tk.StringVar()
checkbox1 = tk.IntVar()
checkbox2 = tk.IntVar()
checkbox3 = tk.IntVar()
radiobtn = tk.IntVar()
radiobtn.set(99)
ttk.Label(widget1, text='First Name: ', font=FONT).grid(row=0, column=0, sticky=tk.W)
ttk.Label(widget1, text='Last Name: ', font=FONT).grid(row=1, column=0, sticky=tk.W)
ttk.Label(widget1, text='Enrollment No.: ', font=FONT).grid(row=2, column=0, sticky=tk.W)
ttk.Label(widget1, text='Degree: ', font=FONT).grid(row=3, column=0, sticky=tk.W)
ttk.Label(widget1, text='Department: ', font=FONT).grid(row=4, column=0, sticky=tk.W)
ttk.Label(widget1, text='Course: ', font=FONT).grid(row=5, column=0, sticky=tk.W)
ttk.Label(widget1, text='Bio: ', font=FONT).grid(row=6, column=0, sticky=tk.W)
# Create Elements
input_fname = ttk.Entry(widget1, width=20, textvariable=fname)
input_lname = ttk.Entry(widget1, width=20, textvariable=lname)
input_enrollment = ttk.Entry(widget1, width=20, textvariable=enrollment)
input_degree = ttk.Combobox(widget1, width=10, textvariable=degree, state='readonly')
input_department = ttk.Combobox(widget1, width=10, textvariable=department, state='readonly')
input_course = ttk.Combobox(widget1, width=30, textvariable=course, state='readonly')
input_degree['values'] = ['BE/BTech', 'ME/MTech', 'BSc', 'MSc']
input_department['values'] = ('EE', 'ECE', 'CSE', 'Other')
input_course['values'] = ('C/C++: Data Structures & Algorithms',
'Python: Data Structures & Algorithms',
'Electic Circuits: Design & Analysis',
'Electronic Circuits: Design & Analysis',
'Circuit Simulation & Design')
input_bio = scrolledtext.ScrolledText(widget1, width=BIO_WIDTH, height=BIO_HEIGHT, wrap=tk.WORD)
input_fname.grid(row=0, column=1)
input_lname.grid(row=1, column=1)
input_enrollment.grid(row=2, column=1)
input_degree.grid(row=3, column=1)
input_department.grid(row=4, column=1)
input_course.grid(row=5, column=1)
input_bio.grid(row=7, column=0, columnspan=3)
# Buttons for executing event handlers
action = ttk.Button(widget1, text='OK', command=ok)
action.grid(row=8, column=1, sticky=tk.E)
# Tab2: Widgets
# Create Elements
input_checkbox1 = tk.Checkbutton(widget2, text='Disabled', variable=checkbox1, state='disabled')
input_checkbox1.select()
input_checkbox2 = tk.Checkbutton(widget2, text='Checked', variable=checkbox2)
input_checkbox2.select()
input_checkbox3 = tk.Checkbutton(widget2, text='UnChecked', variable=checkbox3)
input_checkbox3.deselect()
input_checkbox1.grid(row=1, column=0)
input_checkbox2.grid(row=1, column=1)
input_checkbox3.grid(row=1, column=2)
# Tab3: Widgets
# Create Elements
buttonframe = ttk.LabelFrame(widget3, text='Labels Within A Frame')
buttonframe.grid(row=11, column=0, padx=20, pady=20)
# Horizontal Alignment
ttk.Label(buttonframe, text='X1').grid(row=0, column=1)
ttk.Label(buttonframe, text='X2').grid(row=0, column=2)
ttk.Label(buttonframe, text='X3').grid(row=0, column=3)
# Vertical Alignment
ttk.Label(buttonframe, text='Y1').grid(row=1, column=0)
ttk.Label(buttonframe, text='Y2').grid(row=2, column=0)
ttk.Label(buttonframe, text='Y3').grid(row=3, column=0)
for child in buttonframe.winfo_children():
child.grid_configure(padx=5, pady=5)
for i in range(3):
input_radiobtn = tk.Radiobutton(widget3, text=COLORS[i], variable=radiobtn, value=i, command=change_background)
input_radiobtn.grid(row=9, column=i)
input_fname.focus()
window.resizable(False, False)
window.mainloop()
v2.C
CHANGES:
Added spinbox, progressbar. Removed radiobuttons.
How to use 2+ spinboxes simultaneously with output only when the relevant box's value changes?
import tkinter as tk
from tkinter import ttk, scrolledtext, Menu, messagebox as msg
import webbrowser
from time import sleep
# Define Constants
COLORS = ['Red', 'Green', 'Blue']
# COLORS = [#FF0000,#00FF00,#0000FF]
BIO_WIDTH = 50
BIO_HEIGHT = 5
FONT = ('System', 12, 'bold')
CHOICES = ['Mary', 'had', 'a', 'little', 'lamb']
window = tk.Tk()
window.title('Python GUI')
menubar = Menu(window)
window.configure(menu=menubar)
tabs = ttk.Notebook(window)
# Set PNG image as root logo
img = tk.PhotoImage(file='resources/logos/summit.png')
window.tk.call('wm', 'iconphoto', window._w, img)
# Create Tabs
tab1 = ttk.Frame(tabs)
tab2 = ttk.Frame(tabs)
tab3 = ttk.Frame(tabs)
tabs.add(tab1, text='Tab1')
tabs.add(tab2, text='Tab2')
tabs.add(tab3, text='Tab3')
tabs.pack(expand=1, fill='both')
# Create widgets within tabs
# Tab: 1
widget1 = ttk.LabelFrame(tab1, text='LabelFrame')
widget1.grid(row=0, column=0, padx=10, pady=10)
# Tab: 2
widget2 = ttk.LabelFrame(tab2, text='LabelFrame')
widget2.grid(row=0, column=0, padx=10, pady=10)
# Tab: 3
widget3 = ttk.LabelFrame(tab3, text='LabelFrame')
widget3.grid(row=0, column=0, padx=10, pady=10)
# Event handlers for modifiying labels
def ok():
action.configure(text='Welcome, {}!'.format(fname.get()))
def _quit():
window.quit()
window.destroy()
exit()
def change_background():
choice = radiobtn.get()
if choice == 0:
window.configure(background=COLORS[0])
elif choice == 1:
window.configure(background=COLORS[1])
elif choice == 2:
window.configure(background=COLORS[2])
def _msgbox():
# msg.showinfo('Did You Know?', 'This GUI was created using Tkinter v8.6.')
# msg.showwarning('Warning!', 'Your details may be shared with 3rd Party Apps.')
# msg.showerror('Error!', 'Error: 404\n Page Not Found.')
answer = msg.askyesnocancel('GUI Information', 'Do you want to know more?')
if answer == True:
webbrowser.open('http://www.github.com/CRTejaswi')
def _spin():
value1 = spin1.get()
value2 = spin2.get()
print(value1, value2)
if value1:
scroll1.insert(tk.INSERT, value1 + '\n')
if value2:
scroll2.insert(tk.INSERT, value2 + '\n')
def progressbar_run():
progressbar['maximum'] = 100
for i in range(101):
sleep(0.05)
progressbar['value'] = i
progressbar.update()
progressbar['value'] = 0
def progressbar_start():
progressbar.start()
def progressbar_stop():
progressbar.stop()
def progressbar_stop_delayed(wait_ms=1000):
window.after(wait_ms, progressbar.stop())
# Create Menus
menu_file = Menu(menubar, tearoff=0)
menu_edit = Menu(menubar, tearoff=0)
menu_view = Menu(menubar, tearoff=0)
menu_help = Menu(menubar, tearoff=0)
menu_file.add_command(label='New')
menu_file.add_command(label='Open')
menu_file.add_command(label='Close')
menu_file.add_command(label='Quit', command=_quit)
menu_file.add_command(label='Save')
menu_file.add_command(label='Save As')
menu_file.add_command(label='Print')
menubar.add_cascade(label='File', menu=menu_file)
menu_edit.add_command(label='Cut')
menu_edit.add_command(label='Copy')
menu_edit.add_command(label='Paste')
menu_edit.add_command(label='Find')
menu_edit.add_command(label='Replace')
menubar.add_cascade(label='Edit', menu=menu_edit)
menu_view.add_command(label='Status Bar')
menubar.add_cascade(label='View', menu=menu_view)
menu_help.add_command(label='About', command=_msgbox)
menubar.add_cascade(label='Help', menu=menu_help)
# Tab1: Widgets
# Create Labels
fname = tk.StringVar()
lname = tk.StringVar()
enrollment = tk.StringVar()
degree = tk.StringVar()
department = tk.StringVar()
course = tk.StringVar()
checkbox1 = tk.IntVar()
checkbox2 = tk.IntVar()
checkbox3 = tk.IntVar()
radiobtn = tk.IntVar()
radiobtn.set(99)
ttk.Label(widget1, text='First Name: ', font=FONT).grid(row=0, column=0, sticky=tk.W)
ttk.Label(widget1, text='Last Name: ', font=FONT).grid(row=1, column=0, sticky=tk.W)
ttk.Label(widget1, text='Enrollment No.: ', font=FONT).grid(row=2, column=0, sticky=tk.W)
ttk.Label(widget1, text='Degree: ', font=FONT).grid(row=3, column=0, sticky=tk.W)
ttk.Label(widget1, text='Department: ', font=FONT).grid(row=4, column=0, sticky=tk.W)
ttk.Label(widget1, text='Course: ', font=FONT).grid(row=5, column=0, sticky=tk.W)
ttk.Label(widget1, text='Bio: ', font=FONT).grid(row=6, column=0, sticky=tk.W)
# Create Elements
input_fname = ttk.Entry(widget1, width=20, textvariable=fname)
input_lname = ttk.Entry(widget1, width=20, textvariable=lname)
input_enrollment = ttk.Entry(widget1, width=20, textvariable=enrollment)
input_degree = ttk.Combobox(widget1, width=10, textvariable=degree, state='readonly')
input_department = ttk.Combobox(widget1, width=10, textvariable=department, state='readonly')
input_course = ttk.Combobox(widget1, width=30, textvariable=course, state='readonly')
input_degree['values'] = ['BE/BTech', 'ME/MTech', 'BSc', 'MSc']
input_department['values'] = ('EE', 'ECE', 'CSE', 'Other')
input_course['values'] = ('C/C++: Data Structures & Algorithms',
'Python: Data Structures & Algorithms',
'Electic Circuits: Design & Analysis',
'Electronic Circuits: Design & Analysis',
'Circuit Simulation & Design')
input_bio = scrolledtext.ScrolledText(widget1, width=BIO_WIDTH, height=BIO_HEIGHT, wrap=tk.WORD)
input_fname.grid(row=0, column=1)
input_lname.grid(row=1, column=1)
input_enrollment.grid(row=2, column=1)
input_degree.grid(row=3, column=1)
input_department.grid(row=4, column=1)
input_course.grid(row=5, column=1)
input_bio.grid(row=7, column=0, columnspan=3)
# Buttons for executing event handlers
action = ttk.Button(widget1, text='OK', command=ok)
action.grid(row=8, column=1, sticky=tk.E)
# Tab2: Widgets
# Create Elements
input_checkbox1 = tk.Checkbutton(widget2, text='Disabled', variable=checkbox1, state='disabled')
input_checkbox1.select()
input_checkbox2 = tk.Checkbutton(widget2, text='Checked', variable=checkbox2)
input_checkbox2.select()
input_checkbox3 = tk.Checkbutton(widget2, text='UnChecked', variable=checkbox3)
input_checkbox3.deselect()
input_checkbox1.grid(row=1, column=0)
input_checkbox2.grid(row=1, column=1)
input_checkbox3.grid(row=1, column=2)
ttk.Label(widget2, text='Spin the Bottle: ', font=FONT).grid(row=2, column=0, sticky=tk.W)
spin1 = ttk.Spinbox(widget2, from_=0, to=10, width=5, command=_spin)
spin1.grid(row=2, column=1, sticky=tk.W)
scroll1 = scrolledtext.ScrolledText(widget2, width=10, height=20, wrap=tk.WORD)
scroll1.grid(row=3, column=1)
ttk.Label(widget2, text='Spin the Bottle: ', font=FONT).grid(row=2, column=2, sticky=tk.W)
spin2 = ttk.Spinbox(widget2, values=CHOICES, width=5, command=_spin)
spin2.grid(row=2, column=3, sticky=tk.W)
scroll2 = scrolledtext.ScrolledText(widget2, width=10, height=20, wrap=tk.WORD)
scroll2.grid(row=3, column=3)
# Tab3: Widgets
# Progress Bar
ttk.Button(widget3, text='Run', command=progressbar_run).grid(row=2, column=0)
ttk.Button(widget3, text='Start', command=progressbar_start).grid(row=1, column=1)
ttk.Button(widget3, text='Stop', command=progressbar_stop).grid(row=2, column=1)
ttk.Button(widget3, text='Stop (+1s)', command=progressbar_stop_delayed).grid(row=3, column=1)
progressbar = ttk.Progressbar(tab3, orient='horizontal', length=512, mode='determinate')
progressbar.grid(row=3, column=0, padx=5, pady=5)
input_fname.focus()
window.resizable(False, False)
window.mainloop()
v2.D
CHANGES: Added tooltips.
import tkinter as tk
from tkinter import ttk, scrolledtext, Menu, messagebox as msg
import webbrowser
from time import sleep
# Define Constants
COLORS = ['Red', 'Green', 'Blue']
# COLORS = [#FF0000,#00FF00,#0000FF]
BIO_WIDTH = 50
BIO_HEIGHT = 5
FONT = ('System', 12, 'bold')
CHOICES = ['Mary', 'had', 'a', 'little', 'lamb']
window = tk.Tk()
window.title('Python GUI')
menubar = Menu(window)
window.configure(menu=menubar)
tabs = ttk.Notebook(window)
# Set PNG image as root logo
img = tk.PhotoImage(file='resources/logos/summit.png')
window.tk.call('wm', 'iconphoto', window._w, img)
""" Class: ToolTip
- Creates a tooltip that displays info when mouse pointer is hovered over the element.
"""
class ToolTip(object):
def __init__(self, widget):
self.widget = widget
self.tip_window = None
def show_tip(self, tip_text):
# Display info in a tooltip window
if self.tip_window or not tip_text:
return
x, y, cx, cy = self.widget.bbox('insert')
x = x + self.widget.winfo_rootx() + 25
y = y + cy + self.widget.winfo_rooty() + 25
self.tip_window = tw = tk.Toplevel(self.widget)
tw.wm_overrideredirect(True)
tw. wm_geometry('+%d+%d' % (x, y))
label = tk.Label(tw, text=tip_text, justify=tk.LEFT,
background='#FFFFE0', relief=tk.SOLID, borderwidth=1,
font=FONT)
label.pack(ipadx=1)
def hide_tip(self):
tw = self.tip_window
self.tip_window = None
if tw:
tw.destroy()
# Create Tabs
tab1 = ttk.Frame(tabs)
tab2 = ttk.Frame(tabs)
tab3 = ttk.Frame(tabs)
tabs.add(tab1, text='Tab1')
tabs.add(tab2, text='Tab2')
tabs.add(tab3, text='Tab3')
tabs.pack(expand=1, fill='both')
# Create widgets within tabs
# Tab: 1
widget1 = ttk.LabelFrame(tab1, text='LabelFrame')
widget1.grid(row=0, column=0, padx=10, pady=10)
# Tab: 2
widget2 = ttk.LabelFrame(tab2, text='LabelFrame')
widget2.grid(row=0, column=0, padx=10, pady=10)
# Tab: 3
widget3 = ttk.LabelFrame(tab3, text='LabelFrame')
widget3.grid(row=0, column=0, padx=10, pady=10)
# Event handlers for modifiying labels
def ok():
action.configure(text='Welcome, {}!'.format(fname.get()))
def _quit():
window.quit()
window.destroy()
exit()
def change_background():
choice = radiobtn.get()
if choice == 0:
window.configure(background=COLORS[0])
elif choice == 1:
window.configure(background=COLORS[1])
elif choice == 2:
window.configure(background=COLORS[2])
def _msgbox():
# msg.showinfo('Did You Know?', 'This GUI was created using Tkinter v8.6.')
# msg.showwarning('Warning!', 'Your details may be shared with 3rd Party Apps.')
# msg.showerror('Error!', 'Error: 404\n Page Not Found.')
answer = msg.askyesnocancel('GUI Information', 'Do you want to know more?')
if answer == True:
webbrowser.open('http://www.github.com/CRTejaswi')
def _spin():
value1 = spin1.get()
value2 = spin2.get()
print(value1, value2)
if value1:
scroll1.insert(tk.INSERT, value1 + '\n')
if value2:
scroll2.insert(tk.INSERT, value2 + '\n')
def progressbar_run():
progressbar['maximum'] = 100
for i in range(101):
sleep(0.05)
progressbar['value'] = i
progressbar.update()
progressbar['value'] = 0
def progressbar_start():
progressbar.start()
def progressbar_stop():
progressbar.stop()
def progressbar_stop_delayed(wait_ms=1000):
window.after(wait_ms, progressbar.stop())
def create_tooltip(widget, text):
tooltip = ToolTip(widget)
def enter(event):
tooltip.show_tip(text)
def leave(event):
tooltip.hide_tip()
# Bind mouse events
widget.bind('<Enter>', enter)
widget.bind('<Leave>', leave)
# Create Menus
menu_file = Menu(menubar, tearoff=0)
menu_edit = Menu(menubar, tearoff=0)
menu_view = Menu(menubar, tearoff=0)
menu_help = Menu(menubar, tearoff=0)
menu_file.add_command(label='New')
menu_file.add_command(label='Open')
menu_file.add_command(label='Close')
menu_file.add_command(label='Quit', command=_quit)
menu_file.add_command(label='Save')
menu_file.add_command(label='Save As')
menu_file.add_command(label='Print')
menubar.add_cascade(label='File', menu=menu_file)
menu_edit.add_command(label='Cut')
menu_edit.add_command(label='Copy')
menu_edit.add_command(label='Paste')
menu_edit.add_command(label='Find')
menu_edit.add_command(label='Replace')
menubar.add_cascade(label='Edit', menu=menu_edit)
menu_view.add_command(label='Status Bar')
menubar.add_cascade(label='View', menu=menu_view)
menu_help.add_command(label='About', command=_msgbox)
menubar.add_cascade(label='Help', menu=menu_help)
# Tab1: Widgets
# Create Labels
fname = tk.StringVar()
lname = tk.StringVar()
enrollment = tk.StringVar()
degree = tk.StringVar()
department = tk.StringVar()
course = tk.StringVar()
checkbox1 = tk.IntVar()
checkbox2 = tk.IntVar()
checkbox3 = tk.IntVar()
radiobtn = tk.IntVar()
radiobtn.set(99)
ttk.Label(widget1, text='First Name: ', font=FONT).grid(row=0, column=0, sticky=tk.W)
ttk.Label(widget1, text='Last Name: ', font=FONT).grid(row=1, column=0, sticky=tk.W)
ttk.Label(widget1, text='Enrollment No.: ', font=FONT).grid(row=2, column=0, sticky=tk.W)
ttk.Label(widget1, text='Degree: ', font=FONT).grid(row=3, column=0, sticky=tk.W)
ttk.Label(widget1, text='Department: ', font=FONT).grid(row=4, column=0, sticky=tk.W)
ttk.Label(widget1, text='Course: ', font=FONT).grid(row=5, column=0, sticky=tk.W)
ttk.Label(widget1, text='Bio: ', font=FONT).grid(row=6, column=0, sticky=tk.W)
# Create Elements
input_fname = ttk.Entry(widget1, width=20, textvariable=fname)
input_lname = ttk.Entry(widget1, width=20, textvariable=lname)
input_enrollment = ttk.Entry(widget1, width=20, textvariable=enrollment)
input_degree = ttk.Combobox(widget1, width=10, textvariable=degree, state='readonly')
input_department = ttk.Combobox(widget1, width=10, textvariable=department, state='readonly')
input_course = ttk.Combobox(widget1, width=30, textvariable=course, state='readonly')
input_degree['values'] = ['BE/BTech', 'ME/MTech', 'BSc', 'MSc']
input_department['values'] = ('EE', 'ECE', 'CSE', 'Other')
input_course['values'] = ('C/C++: Data Structures & Algorithms',
'Python: Data Structures & Algorithms',
'Electic Circuits: Design & Analysis',
'Electronic Circuits: Design & Analysis',
'Circuit Simulation & Design')
input_bio = scrolledtext.ScrolledText(widget1, width=BIO_WIDTH, height=BIO_HEIGHT, wrap=tk.WORD)
input_fname.grid(row=0, column=1)
input_lname.grid(row=1, column=1)
input_enrollment.grid(row=2, column=1)
input_degree.grid(row=3, column=1)
input_department.grid(row=4, column=1)
input_course.grid(row=5, column=1)
input_bio.grid(row=7, column=0, columnspan=3)
# Buttons for executing event handlers
action = ttk.Button(widget1, text='OK', command=ok)
action.grid(row=8, column=1, sticky=tk.E)
# Tab2: Widgets
# Create Elements
input_checkbox1 = tk.Checkbutton(widget2, text='Disabled', variable=checkbox1, state='disabled')
input_checkbox1.select()
input_checkbox2 = tk.Checkbutton(widget2, text='Checked', variable=checkbox2)
input_checkbox2.select()
input_checkbox3 = tk.Checkbutton(widget2, text='UnChecked', variable=checkbox3)
input_checkbox3.deselect()
input_checkbox1.grid(row=1, column=0)
input_checkbox2.grid(row=1, column=1)
input_checkbox3.grid(row=1, column=2)
ttk.Label(widget2, text='Spin the Bottle: ', font=FONT).grid(row=2, column=0, sticky=tk.W)
spin1 = ttk.Spinbox(widget2, from_=0, to=10, width=5, command=_spin)
spin1.grid(row=2, column=1, sticky=tk.W)
scroll1 = scrolledtext.ScrolledText(widget2, width=10, height=20, wrap=tk.WORD)
scroll1.grid(row=3, column=1)
create_tooltip(spin1, 'A numbered (0-10) spin-control.')
ttk.Label(widget2, text='Spin the Bottle: ', font=FONT).grid(row=2, column=2, sticky=tk.W)
spin2 = ttk.Spinbox(widget2, values=CHOICES, width=5, command=_spin)
spin2.grid(row=2, column=3, sticky=tk.W)
scroll2 = scrolledtext.ScrolledText(widget2, width=10, height=20, wrap=tk.WORD)
scroll2.grid(row=3, column=3)
create_tooltip(spin2, 'A text-valued spin-control.')
# Tab3: Widgets
# Progress Bar
ttk.Button(widget3, text='Run', command=progressbar_run).grid(row=2, column=0)
ttk.Button(widget3, text='Start', command=progressbar_start).grid(row=1, column=1)
ttk.Button(widget3, text='Stop', command=progressbar_stop).grid(row=2, column=1)
ttk.Button(widget3, text='Stop (+1s)', command=progressbar_stop_delayed).grid(row=3, column=1)
progressbar = ttk.Progressbar(tab3, orient='horizontal', length=512, mode='determinate')
progressbar.grid(row=3, column=0, padx=5, pady=5)
create_tooltip(progressbar, 'A button-controlled progressbar. Click `Run` to begin.')
input_fname.focus()
window.resizable(False, False)
window.mainloop()`
- How to get data from a widget
- Using module-level global variables
- How coding in classes can improve the GUI
- Writing callback functions
- Creating reusable GUI components
v2.E
CHANGES: Changed source code from procedural to OOP style. Removed Radiobuttons, Spinbox, Scrollbar.
import tkinter as tk
from tkinter import ttk, scrolledtext, Menu, messagebox as msg
import webbrowser
from time import sleep
# Define Constants
FONT = ('System', 12, 'bold')
BIO_WIDTH = 50
BIO_HEIGHT = 5
"""
GUI: Main Display class for the application.
"""
class GUI():
def __init__(self):
self.window = tk.Tk()
self.window.title('Python GUI')
self.window.resizable(False, False)
self.create_widgets()
def ok(self):
self.action.configure(text='Welcome, {}!'.format(self.fname.get()))
def create_widgets(self):
# Tabs
tabs = ttk.Notebook(self.window)
tab1 = ttk.Frame(tabs)
tab2 = ttk.Frame(tabs)
tab3 = ttk.Frame(tabs)
tabs.add(tab1, text='Tab1')
tabs.add(tab2, text='Tab2')
tabs.add(tab3, text='Tab3')
tabs.pack(expand=1, fill='both')
# Entries: Variables
self.fname = tk.StringVar()
self.lname = tk.StringVar()
self.enrollment = tk.StringVar()
self.degree = tk.StringVar()
self.department = tk.StringVar()
self.course = tk.StringVar()
# Entries: Labels
ttk.Label(tab1, text='First Name: ', font=FONT).grid(row=0, column=0, sticky=tk.W)
ttk.Label(tab1, text='Last Name: ', font=FONT).grid(row=1, column=0, sticky=tk.W)
ttk.Label(tab1, text='Enrollment No.: ', font=FONT).grid(row=2, column=0, sticky=tk.W)
ttk.Label(tab1, text='Degree: ', font=FONT).grid(row=3, column=0, sticky=tk.W)
ttk.Label(tab1, text='Department: ', font=FONT).grid(row=4, column=0, sticky=tk.W)
ttk.Label(tab1, text='Course: ', font=FONT).grid(row=5, column=0, sticky=tk.W)
ttk.Label(tab1, text='Bio: ', font=FONT).grid(row=6, column=0, sticky=tk.W)
# Entries: Values
input_fname = ttk.Entry(tab1, width=20, textvariable=self.fname)
input_lname = ttk.Entry(tab1, width=20, textvariable=self.lname)
input_enrollment = ttk.Entry(tab1, width=20, textvariable=self.enrollment)
input_degree = ttk.Combobox(tab1, width=10, textvariable=self.degree, state='readonly')
input_department = ttk.Combobox(tab1, width=10, textvariable=self.department, state='readonly')
input_course = ttk.Combobox(tab1, width=30, textvariable=self.course, state='readonly')
input_degree['values'] = ['BE/BTech', 'ME/MTech', 'BSc', 'MSc']
input_department['values'] = ('EE', 'ECE', 'CSE', 'Other')
input_course['values'] = ('C/C++: Data Structures & Algorithms',
'Python: Data Structures & Algorithms',
'Electic Circuits: Design & Analysis',
'Electronic Circuits: Design & Analysis',
'Circuit Simulation & Design')
input_bio = scrolledtext.ScrolledText(tab1, width=BIO_WIDTH, height=BIO_HEIGHT, wrap=tk.WORD)
# Entries: Formatting & Alignment
input_fname.grid(row=0, column=1)
input_lname.grid(row=1, column=1)
input_enrollment.grid(row=2, column=1)
input_degree.grid(row=3, column=1)
input_department.grid(row=4, column=1)
input_course.grid(row=5, column=1)
input_bio.grid(row=7, column=0, columnspan=3, padx=10, pady=10)
# Buttons: Labels & Formatting
self.action = ttk.Button(tab1, text='OK', command=self.ok)
self.action.grid(row=8, column=1, sticky=tk.E)
input_fname.focus()
app = GUI()
app.window.mainloop()
v2.F
CHANGES: Re-added Spinbox controls, tooltip.
tooltip
is imported from a separateutilities
module.
# utilities.py
import tkinter as tk
FONT = ('System', 12, 'bold')
""" Class: ToolTip
- Creates a tooltip that displays info when mouse pointer is hovered over the element.
"""
class ToolTip(object):
def __init__(self, widget):
self.widget = widget
self.tip_window = None
def show_tip(self, tip_text):
# Display info in a tooltip window
if self.tip_window or not tip_text:
return
x, y, cx, cy = self.widget.bbox('insert')
x = x + self.widget.winfo_rootx() + 25
y = y + cy + self.widget.winfo_rooty() + 25
self.tip_window = tw = tk.Toplevel(self.widget)
tw.wm_overrideredirect(True)
tw. wm_geometry('+%d+%d' % (x, y))
label = tk.Label(tw, text=tip_text, justify=tk.LEFT,
background='#FFFFE0', relief=tk.SOLID, borderwidth=1,
font=FONT)
label.pack(ipadx=1)
def hide_tip(self):
tw = self.tip_window
self.tip_window = None
if tw:
tw.destroy()
def create_tooltip(widget, text):
tooltip = ToolTip(widget)
def enter(event):
try:
tooltip.show_tip(text)
except:
pass
def leave(event):
tooltip.hide_tip()
# Bind mouse events
widget.bind('<Enter>', enter)
widget.bind('<Leave>', leave)
import tkinter as tk
from tkinter import ttk, scrolledtext, Menu, messagebox as msg
import webbrowser
from time import sleep
from utilities import ToolTip as tt
# Define Constants
FONT = ('System', 12, 'bold')
BIO_WIDTH = 50
BIO_HEIGHT = 5
CHOICES = ['Mary', 'had', 'a', 'little', 'lamb']
"""
GUI: Main Display class for the application.
"""
class GUI():
def __init__(self):
self.window = tk.Tk()
self.window.title('Python GUI')
self.window.resizable(False, False)
self.create_widgets()
def ok(self):
self.action.configure(text='Welcome, {}!'.format(self.fname.get()))
def _spin(self):
value1 = self.spin1.get()
value2 = self.spin2.get()
print(value1, value2)
if value1:
self.scroll1.insert(tk.INSERT, value1 + '\n')
if value2:
self.scroll2.insert(tk.INSERT, value2 + '\n')
def create_widgets(self):
# Tabs
tabs = ttk.Notebook(self.window)
tab1 = ttk.Frame(tabs)
tab2 = ttk.Frame(tabs)
tab3 = ttk.Frame(tabs)
tabs.add(tab1, text='Tab1')
tabs.add(tab2, text='Tab2')
tabs.add(tab3, text='Tab3')
tabs.pack(expand=1, fill='both')
tt.create_tooltip(tab1, 'Gather basic user info')
tt.create_tooltip(tab2, 'Example: Using Spinbox control')
tt.create_tooltip(tab3, 'Example: Using ProgressBar')
# Tab: 1
# Entries: Variables
self.fname = tk.StringVar()
self.lname = tk.StringVar()
self.enrollment = tk.StringVar()
self.degree = tk.StringVar()
self.department = tk.StringVar()
self.course = tk.StringVar()
# Entries: Labels
ttk.Label(tab1, text='First Name: ', font=FONT).grid(row=0, column=0, sticky=tk.W)
ttk.Label(tab1, text='Last Name: ', font=FONT).grid(row=1, column=0, sticky=tk.W)
ttk.Label(tab1, text='Enrollment No.: ', font=FONT).grid(row=2, column=0, sticky=tk.W)
ttk.Label(tab1, text='Degree: ', font=FONT).grid(row=3, column=0, sticky=tk.W)
ttk.Label(tab1, text='Department: ', font=FONT).grid(row=4, column=0, sticky=tk.W)
ttk.Label(tab1, text='Course: ', font=FONT).grid(row=5, column=0, sticky=tk.W)
ttk.Label(tab1, text='Bio: ', font=FONT).grid(row=6, column=0, sticky=tk.W)
# Entries: Values
input_fname = ttk.Entry(tab1, width=20, textvariable=self.fname)
input_lname = ttk.Entry(tab1, width=20, textvariable=self.lname)
input_enrollment = ttk.Entry(tab1, width=20, textvariable=self.enrollment)
input_degree = ttk.Combobox(tab1, width=10, textvariable=self.degree, state='readonly')
input_department = ttk.Combobox(tab1, width=10, textvariable=self.department, state='readonly')
input_course = ttk.Combobox(tab1, width=30, textvariable=self.course, state='readonly')
input_degree['values'] = ['BE/BTech', 'ME/MTech', 'BSc', 'MSc']
input_department['values'] = ('EE', 'ECE', 'CSE', 'Other')
input_course['values'] = ('C/C++: Data Structures & Algorithms',
'Python: Data Structures & Algorithms',
'Electic Circuits: Design & Analysis',
'Electronic Circuits: Design & Analysis',
'Circuit Simulation & Design')
input_bio = scrolledtext.ScrolledText(tab1, width=BIO_WIDTH, height=BIO_HEIGHT, wrap=tk.WORD)
# Entries: Formatting & Alignment
input_fname.grid(row=0, column=1)
input_lname.grid(row=1, column=1)
input_enrollment.grid(row=2, column=1)
input_degree.grid(row=3, column=1)
input_department.grid(row=4, column=1)
input_course.grid(row=5, column=1)
input_bio.grid(row=7, column=0, columnspan=3, padx=10, pady=10)
# Buttons: Labels & Formatting
self.action = ttk.Button(tab1, text='OK', command=self.ok)
self.action.grid(row=8, column=1, sticky=tk.E)
input_fname.focus()
# Tab: 2
ttk.Label(tab2, text='Spin the Bottle: ', font=FONT).grid(row=2, column=0, sticky=tk.W)
self.spin1 = ttk.Spinbox(tab2, from_=0, to=10, width=5, command=self._spin)
self.spin1.grid(row=2, column=1, sticky=tk.W)
self.scroll1 = scrolledtext.ScrolledText(tab2, width=10, height=20, wrap=tk.WORD)
self.scroll1.grid(row=3, column=1)
tt.create_tooltip(self.spin1, 'A numbered (0-10) spin-control.')
ttk.Label(tab2, text='Spin the Bottle: ', font=FONT).grid(row=2, column=2, sticky=tk.W)
self.spin2 = ttk.Spinbox(tab2, values=CHOICES, width=5, command=self._spin)
self.spin2.grid(row=2, column=3, sticky=tk.W)
self.scroll2 = scrolledtext.ScrolledText(tab2, width=10, height=20, wrap=tk.WORD)
self.scroll2.grid(row=3, column=3)
tt.create_tooltip(self.spin2, 'A text-valued spin-control.')
app = GUI()
app.window.mainloop()
v5.1
import numpy as np
from matplotlib.figure import Figure
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
import tkinter as tk
import math
# Constants
PI = math.pi
x = np.arange(-10 * PI, 10 * PI, 0.1)
y1 = np.sin(x)
y2 = np.cos(x)
y3 = np.tan(x)
y4 = np.arcsin(x)
y5 = np.arccos(x)
y6 = np.arctan(x)
figure = Figure(figsize=(12, 8), facecolor='#FFFFFF')
axis1 = figure.add_subplot(231)
axis1.plot(x, y1, color='#FF0000')
axis1.set_xlabel('Radians')
axis1.set_ylabel('sin(x)')
axis1.grid(linestyle='--')
axis2 = figure.add_subplot(232)
axis2.plot(x, y2, color='#0000FF')
axis2.set_xlabel('Radians')
axis2.set_ylabel('cos(x)')
axis2.grid(linestyle='--')
axis3 = figure.add_subplot(233)
axis3.plot(x, y3, color='#000000')
axis3.set_xlabel('Radians')
axis3.set_ylabel('tan(x)')
axis3.grid(linestyle='--')
axis4 = figure.add_subplot(234)
axis4.plot(x, y4, color='#FF0000')
axis4.set_xlabel('Ratio')
axis4.set_ylabel('arcsin(x)')
axis4.grid(linestyle='--')
axis5 = figure.add_subplot(235)
axis5.plot(x, y5, color='#0000FF')
axis5.set_xlabel('Ratio')
axis5.set_ylabel('arccos(x)')
axis5.grid(linestyle='--')
axis6 = figure.add_subplot(236)
axis6.plot(x, y6, color='#000000')
axis6.set_xlabel('Ratio')
axis6.set_ylabel('arctan(x)')
axis6.grid(linestyle='--')
def _destroyWindow():
root.quit()
root.destroy()
root = tk.Tk()
root.withdraw()
root.protocol('WM_DELETE_WINDOW', _destroyWindow)
canvas = FigureCanvasTkAgg(figure, master=root)
canvas._tkcanvas.pack(side=tk.TOP, fill=tk.BOTH, expand=1)
root.update()
root.deiconify()
root.mainloop()
v5.2
CHANGES: Compact v1.1.
import numpy as np
from matplotlib.figure import Figure
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
import tkinter as tk
import math
# Constants
PI = math.pi
COLORS = ['#FF0000', '#0000FF', '#000000',
'#FF0000', '#0000FF', '#000000']
XLABEL = ['Radians', 'Radians', 'Radians',
'Ratio', 'Ratio', 'Ratio']
YLABEL = ['sin(x)', 'cos(x)', 'tan(x)',
'arcsin(x)', 'arccos(x)', 'arctan(x)']
x = np.arange(-10 * PI, 10 * PI, 0.1)
y = [np.sin(x), np.cos(x), np.tan(x),
np.arcsin(x), np.arccos(x), np.arctan(x)]
figure = Figure(figsize=(12, 8), facecolor='#FFFFFF')
axes = []
axes.set_ylim(-5, 5)
for i in range(6):
axes.append(figure.add_subplot(231 + i))
for i, axis in enumerate(axes):
axis.plot(x, y[i], color=COLORS[i])
axis.set_xlabel(XLABEL[i])
axis.set_ylabel(YLABEL[i])
axis.grid(linestyle='--')
def _destroyWindow():
root.quit()
root.destroy()
root = tk.Tk()
root.withdraw()
root.protocol('WM_DELETE_WINDOW', _destroyWindow)
canvas = FigureCanvasTkAgg(figure, master=root)
canvas._tkcanvas.pack(side=tk.TOP, fill=tk.BOTH, expand=1)
root.update()
root.deiconify()
root.mainloop()
v5.3
CHANGES: Added legends & scaling (
axis.set_ylim()
).
import numpy as np
from matplotlib.figure import Figure
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
import tkinter as tk
import math
# Constants
PI = math.pi
COLORS = ['#FF0000', '#0000FF', '#000000',
'#00FF00', '#FF6600', '#C0C0C0']
XLABEL = ['Radians', 'Radians', 'Radians',
'Ratio', 'Ratio', 'Ratio']
YLABEL = ['sin(x)', 'cos(x)', 'tan(x)',
'arcsin(x)', 'arccos(x)', 'arctan(x)']
x = np.arange(-5 * PI, 5 * PI, 0.1)
y = [np.sin(x), np.cos(x), np.tan(x),
np.arcsin(x), np.arccos(x), np.arctan(x)]
figure = Figure(figsize=(12, 8), facecolor='#FFFFFF')
axis = figure.add_subplot(111)
axis.set_ylim(-5, 5)
for i in range(6):
axis.plot(x, y[i], color=COLORS[i], label=YLABEL[i])
axis.set_xlabel('Radian / Ratio')
axis.set_ylabel('Function')
axis.grid(linestyle='--')
figure.legend()
def _destroyWindow():
root.quit()
root.destroy()
root = tk.Tk()
root.withdraw()
root.protocol('WM_DELETE_WINDOW', _destroyWindow)
canvas = FigureCanvasTkAgg(figure, master=root)
canvas._tkcanvas.pack(side=tk.TOP, fill=tk.BOTH, expand=1)
root.update()
root.deiconify()
root.mainloop()
We may encounter events that cause a delay in program execution. This may be due to a simple wait operation, or expecting a response from user/process/server. To deal with such issues we use threads
to isolate individual events, and queues
to display their results/responses (in a pre-determined manner) in the GUI.
- We can create a thread using the
threading.Thread(target[, args])
method. - The thread can be created through a callback function, which then runs the thread & executes a targetted method in the new thread.
- To stop the thread, we have to convert it into a
daemon
(background) process. When the GUI is closed, all daemons will be stopped automatically.
v6.1
CHANGES: Moved button event to its own thread.
import tkinter as tk
from tkinter import ttk, scrolledtext
from time import sleep
from utilities import ToolTip as tt
from threading import Thread
# Define Constants
FONT = ('System', 12, 'bold')
CHOICES = ['Mary', 'had', 'a', 'little', 'lamb']
"""
GUI: Main Display class for the application.
"""
class GUI():
def __init__(self):
self.window = tk.Tk()
self.window.title('Python GUI')
self.window.resizable(False, False)
self.create_widgets()
def ok(self):
self.action.configure(text='Welcome, {}!'.format(self.fname.get()))
def _spin(self):
value1 = self.spin1.get()
value2 = self.spin2.get()
if value1:
self.scroll1.insert(tk.INSERT, value1 + '\n')
if value2:
self.scroll2.insert(tk.INSERT, value2 + '\n')
def thread_create(self):
self.run_thread = Thread(target=self.thread_method, daemon=True)
self.run_thread.start()
def thread_method(self):
for i in range(10):
sleep(1)
self.scroll1.insert(tk.INSERT, str(i) + '\n')
def create_widgets(self):
# Tabs
tabs = ttk.Notebook(self.window)
tab1 = ttk.Frame(tabs)
tab2 = ttk.Frame(tabs)
tab3 = ttk.Frame(tabs)
tabs.add(tab1, text='Tab1')
tabs.add(tab2, text='Tab2')
tabs.add(tab3, text='Tab3')
tabs.pack(expand=1, fill='both')
tt.create_tooltip(tab1, 'Gather basic user info')
tt.create_tooltip(tab2, 'Example: Using Spinbox control')
tt.create_tooltip(tab3, 'Example: Using ProgressBar')
tabs.select(tab2) # Focus on Tab2
# Tab: 1
# Tab: 2
ttk.Label(tab2, text='Spin the Bottle: ', font=FONT).grid(row=2, column=0, sticky=tk.W)
self.spin1 = ttk.Spinbox(tab2, from_=0, to=10, width=5, command=self._spin)
self.spin1.grid(row=2, column=1, sticky=tk.W)
self.scroll1 = scrolledtext.ScrolledText(tab2, width=10, height=20, wrap=tk.WORD)
self.scroll1.grid(row=3, column=1)
tt.create_tooltip(self.spin1, 'A numbered (0-10) spin-control.')
ttk.Label(tab2, text='Spin the Bottle: ', font=FONT).grid(row=2, column=2, sticky=tk.W)
self.spin2 = ttk.Spinbox(tab2, values=CHOICES, width=5, command=self._spin)
self.spin2.grid(row=2, column=3, sticky=tk.W)
self.scroll2 = scrolledtext.ScrolledText(tab2, width=10, height=20, wrap=tk.WORD)
self.scroll2.grid(row=3, column=3)
tt.create_tooltip(self.spin2, 'A text-valued spin-control.')
ttk.Button(tab2, text='Autofill', command=self.thread_create).grid(row=5, column=1, sticky=tk.W)
# Tab: 3
app = GUI()
app.window.mainloop()
- We can create a queue using the
queue.Queue()
method. - To load data from & store data to a queue, we use the
.get()
&.put()
methods.
v6.2.1
CHANGES: Button now triggers two events (
_spin_autofill
&queue_response
), both operating in separate threads.
import tkinter as tk
from tkinter import ttk, scrolledtext
from time import sleep
from utilities import ToolTip as tt
from threading import Thread
from queue import Queue
# Define Constants
FONT = ('System', 12, 'bold')
CHOICES = ['Mary', 'had', 'a', 'little', 'lamb']
"""
GUI: Main Display class for the application.
"""
class GUI():
def __init__(self):
self.window = tk.Tk()
self.window.title('Python GUI')
self.window.resizable(False, False)
self.create_widgets()
def ok(self):
self.action.configure(text='Welcome, {}!'.format(self.fname.get()))
def _spin(self):
value1 = self.spin1.get()
value2 = self.spin2.get()
if value1:
self.scroll1.insert(tk.INSERT, value1 + '\n')
if value2:
self.scroll2.insert(tk.INSERT, value2 + '\n')
def _spin_autofill(self):
for i in range(10):
sleep(1)
self.scroll1.insert(tk.INSERT, str(i) + '\n')
def queue_response(self):
queue = Queue()
for i in range(10):
queue.put('>> Queue Response: ' + str(i))
while True:
print(queue.get())
def thread_create(self):
self.thread1 = Thread(target=self._spin_autofill, daemon=True)
self.thread1.start()
self.thread2 = Thread(target=self.queue_response, daemon=True)
self.thread2.start()
def create_widgets(self):
# Tabs
tabs = ttk.Notebook(self.window)
tab1 = ttk.Frame(tabs)
tab2 = ttk.Frame(tabs)
tab3 = ttk.Frame(tabs)
tabs.add(tab1, text='Tab1')
tabs.add(tab2, text='Tab2')
tabs.add(tab3, text='Tab3')
tabs.pack(expand=1, fill='both')
tt.create_tooltip(tab1, 'Gather basic user info')
tt.create_tooltip(tab2, 'Example: Using Spinbox control')
tt.create_tooltip(tab3, 'Example: Using ProgressBar')
tabs.select(tab2) # Focus on Tab2
# Tab: 1
# Tab: 2
ttk.Label(tab2, text='Spin the Bottle: ', font=FONT).grid(row=2, column=0, sticky=tk.W)
self.spin1 = ttk.Spinbox(tab2, from_=0, to=10, width=5, command=self._spin)
self.spin1.grid(row=2, column=1, sticky=tk.W)
self.scroll1 = scrolledtext.ScrolledText(tab2, width=10, height=20, wrap=tk.WORD)
self.scroll1.grid(row=3, column=1)
tt.create_tooltip(self.spin1, 'A numbered (0-10) spin-control.')
ttk.Label(tab2, text='Spin the Bottle: ', font=FONT).grid(row=2, column=2, sticky=tk.W)
self.spin2 = ttk.Spinbox(tab2, values=CHOICES, width=5, command=self._spin)
self.spin2.grid(row=2, column=3, sticky=tk.W)
self.scroll2 = scrolledtext.ScrolledText(tab2, width=10, height=20, wrap=tk.WORD)
self.scroll2.grid(row=3, column=3)
tt.create_tooltip(self.spin2, 'A text-valued spin-control.')
# Create 2 Threads: 1 for autofill, 1 for queueing.
ttk.Button(tab2, text='Autofill', command=self.thread_create).grid(row=5, column=1, sticky=tk.W)
# Tab: 3
app = GUI()
app.window.mainloop()
v6.2.2
CHANGES: Moved queueing to another module (
Queues
).
Clicking the button invokes the_button
callback-function, which (sinceQueue()
is now a instance variable (self.queue
)) allows the main script to access content of theQueues
module through theself
instance.
# Queues.py
def write_to_scroll(instance):
print('Response from Queues module.')
for i in range(10):
instance.queue.put('>> Queue[' + str(i) + '] = ' + str(i))
instance.thread_create()
import tkinter as tk
from tkinter import ttk, scrolledtext
from time import sleep
from utilities import ToolTip as tt
from threading import Thread
from queue import Queue
import Queues
# Define Constants
FONT = ('System', 12, 'bold')
CHOICES = ['Mary', 'had', 'a', 'little', 'lamb']
"""
GUI: Main Display class for the application.
"""
class GUI():
def __init__(self):
self.window = tk.Tk()
self.window.title('Python GUI')
self.window.resizable(False, False)
self.queue = Queue()
self.create_widgets()
def ok(self):
self.action.configure(text='Welcome, {}!'.format(self.fname.get()))
def _button(self):
Queues.write_to_scroll(self)
def _spin(self):
value1 = self.spin1.get()
value2 = self.spin2.get()
if value1:
self.scroll1.insert(tk.INSERT, value1 + '\n')
if value2:
self.scroll2.insert(tk.INSERT, value2 + '\n')
def _spin_autofill(self):
for i in range(10):
sleep(1)
self.scroll1.insert(tk.INSERT, str(i) + '\n')
def queue_response(self):
while True:
print(self.queue.get())
def thread_create(self):
self.thread1 = Thread(target=self._spin_autofill, daemon=True)
self.thread1.start()
self.thread2 = Thread(target=self.queue_response, daemon=True)
self.thread2.start()
def create_widgets(self):
# Tabs
tabs = ttk.Notebook(self.window)
tab1 = ttk.Frame(tabs)
tab2 = ttk.Frame(tabs)
tab3 = ttk.Frame(tabs)
tabs.add(tab1, text='Tab1')
tabs.add(tab2, text='Tab2')
tabs.add(tab3, text='Tab3')
tabs.pack(expand=1, fill='both')
tt.create_tooltip(tab1, 'Gather basic user info')
tt.create_tooltip(tab2, 'Example: Using Spinbox control')
tt.create_tooltip(tab3, 'Example: Using ProgressBar')
tabs.select(tab2) # Focus on Tab2
# Tab: 1
# Tab: 2
ttk.Label(tab2, text='Spin the Bottle: ', font=FONT).grid(row=2, column=0, sticky=tk.W)
self.spin1 = ttk.Spinbox(tab2, from_=0, to=10, width=5, command=self._spin)
self.spin1.grid(row=2, column=1, sticky=tk.W)
self.scroll1 = scrolledtext.ScrolledText(tab2, width=10, height=20, wrap=tk.WORD)
self.scroll1.grid(row=3, column=1)
tt.create_tooltip(self.spin1, 'A numbered (0-10) spin-control.')
ttk.Label(tab2, text='Spin the Bottle: ', font=FONT).grid(row=2, column=2, sticky=tk.W)
self.spin2 = ttk.Spinbox(tab2, values=CHOICES, width=5, command=self._spin)
self.spin2.grid(row=2, column=3, sticky=tk.W)
self.scroll2 = scrolledtext.ScrolledText(tab2, width=10, height=20, wrap=tk.WORD)
self.scroll2.grid(row=3, column=3)
tt.create_tooltip(self.spin2, 'A text-valued spin-control.')
# Create 2 Threads: 1 for autofill, 1 for queueing.
ttk.Button(tab2, text='Autofill', command=self._button).grid(row=5, column=1, sticky=tk.W)
# Tab: 3
app = GUI()
app.window.mainloop()
v6.2.3 [BROKEN]
CHANGES: Implements TCP/IP socket communication between server-client.
- Main script acts as (local) TCP server. Implemented by inheriting from
socketserver
module.- Modified
Queues
module to behave as a TCP client. Implemented usingsocket
module.- TCP Client/Server operate in their own threads.
# Queues.py
from socket import socket, AF_INET, SOCK_STREAM
def write_to_scroll(instance):
print('Response from Queues module.')
socket_client = socket(AF_INET, SOCK_STREAM)
socket_client.connect(('localhost', 24000))
for i in range(10):
instance.queue.put(b'>> Queue[' + bytes(str(i)) + b'] = ' + bytes(str(i)))
received = socket_client.recv(8192).decode()
instance.queue.put(received)
instance.thread_create()
import tkinter as tk
from tkinter import ttk, scrolledtext
from time import sleep
from utilities import ToolTip as tt
from threading import Thread
from queue import Queue
import Queues
from socketserver import BaseRequestHandler, TCPServer
# Define Constants
FONT = ('System', 12, 'bold')
CHOICES = ['Mary', 'had', 'a', 'little', 'lamb']
BIO_WIDTH = 50
BIO_HEIGHT = 5
"""
RequestHandler: Server implementation.
"""
class RequestHandler(BaseRequestHandler):
def handle(self):
print('Server connected to: ', self.client_address)
while True:
response = self.request.recv(512)
if not response:
break
self.request.send(b'Server received: ', response)
def server_start():
server = TCPServer(('', 24000), RequestHandler)
server.serve_forever
"""
GUI: Main Display class for the application.
"""
class GUI():
def __init__(self):
self.window = tk.Tk()
self.window.title('Python GUI')
self.window.resizable(False, False)
self.queue = Queue()
server_thread = Thread(target=server_start, daemon=True)
server_thread.start()
self.create_widgets()
def ok(self):
self.action.configure(text='Welcome, {}!'.format(self.fname.get()))
def _button(self):
Queues.write_to_scroll(self)
def _spin(self):
value1 = self.spin1.get()
self.scroll1.insert(tk.INSERT, value1 + '\n')
def _spin_autofill(self):
for i in range(10):
sleep(1)
self.scroll1.insert(tk.INSERT, str(i) + '\n')
def queue_response(self):
while True:
print(self.queue.get())
def thread_create(self):
self.thread1 = Thread(target=self._spin_autofill, daemon=True)
self.thread1.start()
self.thread2 = Thread(target=self.queue_response, daemon=True)
self.thread2.start()
def create_widgets(self):
# Tabs
tabs = ttk.Notebook(self.window)
tab1 = ttk.Frame(tabs)
tab2 = ttk.Frame(tabs)
tab3 = ttk.Frame(tabs)
tabs.add(tab1, text='Tab1')
tabs.add(tab2, text='Tab2')
tabs.add(tab3, text='Tab3')
tabs.pack(expand=1, fill='both')
tt.create_tooltip(tab1, 'Gather basic user info')
tt.create_tooltip(tab2, 'Example: Using Spinbox control')
tt.create_tooltip(tab3, 'Example: Using ProgressBar')
tabs.select(tab2) # Focus on Tab2
# Tab: 1
# Tab: 2
ttk.Label(tab2, text='Spin the Bottle: ', font=FONT).grid(row=2, column=0, sticky=tk.W)
self.spin1 = ttk.Spinbox(tab2, from_=0, to=10, width=5, command=self._spin)
self.spin1.grid(row=2, column=1, sticky=tk.W)
self.scroll1 = scrolledtext.ScrolledText(tab2, width=BIO_WIDTH, height=3 * BIO_HEIGHT, wrap=tk.WORD)
self.scroll1.grid(row=3, column=1)
tt.create_tooltip(self.spin1, 'A numbered (0-10) spin-control.')
# Create 2 Threads: 1 for autofill, 1 for queueing.
ttk.Button(tab2, text='Autofill', command=self._button).grid(row=5, column=1, sticky=tk.W)
# Tab: 3
app = GUI()
app.window.mainloop()
v6.2.4
CHANGES: Retrieve HTML from URL and save it locally.
# url.py
from tkinter import messagebox as msg
from urllib.request import urlopen
def get_html(link):
try:
http_response = urlopen(link)
html_raw = http_response.read()
html = html_raw.decode()
except Exception as exception:
msg.showerror('Note', 'FAILURE: Unable to retrieve URL!\n' + str(exception))
else:
return html
import tkinter as tk
from tkinter import ttk, messagebox as msg
import url
# link = 'https://en.wikipedia.org/wiki/Python_(programming_language)'
"""
GUI: Main Display class for the application.
"""
class GUI():
def __init__(self):
self.window = tk.Tk()
self.window.title('URL Retriever')
self.window.resizable(False, False)
self.create_widgets()
def _button(self):
link = self.url_link.get()
response = None
if link:
response = url.get_html(link)
if response:
with open('RESPONSE.html', 'w', encoding='utf-8') as file:
file.write('<!-- URL: ' + link + ' -->\n\n')
file.write(response)
msg.showinfo('Note', 'SUCCESS: RESPONSE.html generated!')
def create_widgets(self):
# Labels
self.url_link = tk.StringVar()
# Tabs
tabs = ttk.Notebook(self.window)
tab1 = ttk.Frame(tabs)
tab2 = ttk.Frame(tabs)
tab3 = ttk.Frame(tabs)
tabs.add(tab1, text='Tab1')
tabs.add(tab2, text='Tab2')
tabs.add(tab3, text='Tab3')
tabs.pack(expand=1, fill='both')
tabs.select(tab2) # Focus on Tab2
# Tab: 1
# Tab: 2
# Create 2 Threads: 1 for autofill, 1 for queueing.
ttk.Label(tab2, text='URL: ').grid(row=0, column=0)
URL = ttk.Entry(tab2, width=50, textvariable=self.url_link)
URL.grid(row=0, column=1)
URL.focus()
ttk.Button(tab2, text='Get', command=self._button).grid(row=1, column=1, sticky=tk.E)
# Tab: 3
app = GUI()
app.window.mainloop()
v6.3.1
CHANGES: Removed Thread/Queue structures, Tab2 contents. GUI will
Open
a file &Save As
it elsewhere.
import tkinter as tk
from tkinter import ttk, messagebox as msg, filedialog as fd
from utilities import ToolTip as tt
import shutil
from os import path
# Define Constants
FONT = ('System', 12, 'bold')
BIO_WIDTH = 50
BIO_HEIGHT = 5
DIRECTORY_USER = path.dirname(__file__)
DIRECTORY_SERVER = None
"""
GUI: Main Display class for the application.
"""
class GUI():
def __init__(self):
self.window = tk.Tk()
self.window.title('Python GUI')
self.window.resizable(False, False)
self.create_widgets()
# File-Management Methods
def file_open(self):
file_path = fd.askopenfilename(parent=self.window, initialdir=DIRECTORY_USER)
# print(file_path)
self.input_fileOpen.insert(0, file_path)
if file_path:
self.input_fileOpen.config(state='readonly')
def file_saveas(self):
file_path = fd.asksaveasfilename(parent=self.window, initialdir=DIRECTORY_USER)
# print(file_path)
self.input_fileSaveas.insert(0, file_path)
if file_path:
self.input_fileSaveas.config(state='readonly')
src = self.input_fileOpen.get()
dst = self.input_fileSaveas.get()
# print(dst)
try:
shutil.copy(src, dst)
msg.showinfo('Note', 'SUCCESS: File Copied!')
except FileNotFoundError as error:
msg.showerror('Note', 'FAILURE: File Not Copied!\n' + str(error))
except Exception as exception:
msg.showerror('Note', 'FAILURE: File Not Copied!\n' + str(exception))
# Widget-Creation Method
def create_widgets(self):
# Create Labels
file = tk.StringVar()
directory = tk.StringVar()
# Tabs
tabs = ttk.Notebook(self.window)
tab1 = ttk.Frame(tabs)
tab2 = ttk.Frame(tabs)
tab3 = ttk.Frame(tabs)
tabs.add(tab1, text='Tab1')
tabs.add(tab2, text='Tab2')
tabs.add(tab3, text='Tab3')
tabs.pack(expand=1, fill='both')
tt.create_tooltip(tab1, 'Gather basic user info')
tt.create_tooltip(tab2, 'Example: Using Spinbox control')
tt.create_tooltip(tab3, 'Example: Copy File')
tabs.select(tab3) # Focus on Tab2
# Tab: 1
# Tab: 2
# Tab: 3
filemanager = ttk.LabelFrame(tab3, text='File Manager')
filemanager.grid(row=0, column=0, sticky=tk.W, padx=10, pady=10)
fileOpen = ttk.Button(filemanager, text='Open', command=self.file_open)
fileSaveas = ttk.Button(filemanager, text='Save As', command=self.file_saveas)
self.input_fileOpen = ttk.Entry(filemanager, width=BIO_WIDTH, textvariable=file)
self.input_fileSaveas = ttk.Entry(filemanager, width=BIO_WIDTH, textvariable=directory)
fileOpen.grid(row=0, column=0, sticky=tk.W)
self.input_fileOpen.grid(row=0, column=1, sticky=tk.W)
fileSaveas.grid(row=1, column=0, sticky=tk.W)
self.input_fileSaveas.grid(row=1, column=1, sticky=tk.W)
app = GUI()
app.window.mainloop()
v6.3.2
CHANGES: Added
Save To
(directory) option.
import tkinter as tk
from tkinter import ttk, messagebox as msg, filedialog as fd
from utilities import ToolTip as tt
import shutil
from os import path
# Define Constants
FONT = ('System', 12, 'bold')
BIO_WIDTH = 50
BIO_HEIGHT = 5
DIRECTORY_USER = path.dirname(__file__)
DIRECTORY_SERVER = None
"""
GUI: Main Display class for the application.
"""
class GUI():
def __init__(self):
self.window = tk.Tk()
self.window.title('Python GUI')
self.window.resizable(False, False)
self.queue = Queue()
self.create_widgets()
# File-Management Methods
def file_open(self):
file_path = fd.askopenfilename(parent=self.window, initialdir=DIRECTORY_USER)
# print(file_path)
self.input_fileOpen.insert(0, file_path)
if file_path:
self.input_fileOpen.config(state='readonly')
def file_saveas(self):
file_path = fd.asksaveasfilename(parent=self.window, initialdir=DIRECTORY_USER)
# print(file_path)
self.input_fileSaveas.insert(0, file_path)
if file_path:
self.input_fileSaveas.config(state='readonly')
src = self.input_fileOpen.get()
dst = self.input_fileSaveas.get()
# print(dst)
try:
shutil.copy(src, dst)
msg.showinfo('Note', 'SUCCESS: File Copied!')
except FileNotFoundError as error:
msg.showerror('Note', 'FAILURE: File Not Copied!\n' + str(error))
except Exception as exception:
msg.showerror('Note', 'FAILURE: File Not Copied!\n' + str(exception))
def file_saveto(self):
directory_path = fd.askdirectory(parent=self.window, initialdir=DIRECTORY_USER)
# print(directory_path)
self.input_fileSaveto.insert(0, directory_path)
if directory_path:
self.input_fileSaveto.config(state='readonly')
src = self.input_fileOpen.get()
file = src.split('/')[-1]
dst = self.input_fileSaveto.get() + file
dst = self.input_fileSaveto.get()
# print(dst)
try:
shutil.copy(src, dst)
msg.showinfo('Note', 'SUCCESS: File Copied!')
except FileNotFoundError as error:
msg.showerror('Note', 'FAILURE: File Not Copied!\n' + str(error))
except Exception as exception:
msg.showerror('Note', 'FAILURE: File Not Copied!\n' + str(exception))
# Widget-Creation Method
def create_widgets(self):
# Tabs
tabs = ttk.Notebook(self.window)
tab1 = ttk.Frame(tabs)
tab2 = ttk.Frame(tabs)
tab3 = ttk.Frame(tabs)
tabs.add(tab1, text='Tab1')
tabs.add(tab2, text='Tab2')
tabs.add(tab3, text='Tab3')
tabs.pack(expand=1, fill='both')
tt.create_tooltip(tab1, 'Gather basic user info')
tt.create_tooltip(tab2, 'Example: Using Spinbox control')
tt.create_tooltip(tab3, 'Example: Copy File')
tabs.select(tab3) # Focus on Tab2
# Tab: 1
# Tab: 2
# Tab: 3
filemanager = ttk.LabelFrame(tab3, text='File Manager')
filemanager.grid(row=0, column=0, sticky=tk.W, padx=10, pady=10)
fileOpen = ttk.Button(filemanager, text='Open', command=self.file_open)
fileSaveas = ttk.Button(filemanager, text='Save As', command=self.file_saveas)
fileSaveto = ttk.Button(filemanager, text='Save To', command=self.file_saveto)
self.input_fileOpen = ttk.Entry(filemanager, width=BIO_WIDTH)
self.input_fileSaveas = ttk.Entry(filemanager, width=BIO_WIDTH)
self.input_fileSaveto = ttk.Entry(filemanager, width=BIO_WIDTH)
fileOpen.grid(row=0, column=0, sticky=tk.W)
self.input_fileOpen.grid(row=0, column=1, sticky=tk.W)
fileSaveas.grid(row=1, column=0, sticky=tk.W)
self.input_fileSaveas.grid(row=1, column=1, sticky=tk.W)
fileSaveto.grid(row=2, column=0, sticky=tk.W)
self.input_fileSaveto.grid(row=2, column=1, sticky=tk.W)
app = GUI()
app.window.mainloop()
CRUD operations can be performed on a database in Python3 using the in-built sqlite3
module. SQLAlchemy
, an ORM, can be used in addition to connect to larger databases.
- A database can be of type
:memory:
orfile.db
.:memory:
is stored on RAM, and creates a new database on every execution.file.db
is a file stored on harddrive. The former is useful when testing code to avoid loss of data. - The steps to manage a database are:
- Create a connection to database.
- Create a cursor to execute SQL commands.
- Make changes to, or query the database.
- Commit changes to database.
- Close the connection to database.
v7.1
CHANGES: Played with SQLite databases.
- Direct Insertions
import sqlite3
connection = sqlite3.connect(':memory:')
cursor = connection.cursor()
cursor.execute(""" create table employees (
fname text,
lname text,
pay integer
)""")
cursor.execute("INSERT INTO employees VALUES ('John', 'Doe', 50000)")
cursor.execute("INSERT INTO employees VALUES ('Mary', 'Jane', 70000)")
cursor.execute("INSERT INTO employees VALUES ('George', 'Doe', 35000)")
cursor.execute("INSERT INTO employees VALUES ('Josie', 'Jane', 37000)")
cursor.execute("SELECT * FROM employees WHERE lname='Doe'")
print(cursor.fetchall())
connection.commit()
connection.close()
[('John', 'Doe', 50000), ('George', 'Doe', 35000)]
- Indirect Insertions
# employee.py
class Employee:
def __init__(self, fname, lname, pay):
self.fname = fname
self.lname = lname
self.pay = pay
@property
def email(self):
return '{}_{}@email.com'.format(self.fname, self.lname)
@property
def name(self):
return '{} {}'.format(self.fname, self.lname)
def __repr__(self):
return "Employee('{}', '{}', '{}')".format(self.fname, self.lname, self.pay)
import sqlite3
from employee import Employee
connection = sqlite3.connect(':memory:')
cursor = connection.cursor()
cursor.execute(""" create table employees (
fname text,
lname text,
pay integer
)""")
emp1 = Employee('John', 'Doe', 50000)
emp2 = Employee('Mary', 'Jane', 70000)
emp3 = Employee('George', 'Doe', 35000)
emp4 = Employee('Josie', 'Jane', 37000)
cursor.execute("INSERT INTO employees VALUES (?,?,?)", (emp1.fname, emp1.lname, emp1.pay))
cursor.execute("INSERT INTO employees VALUES (?,?,?)", (emp2.fname, emp2.lname, emp2.pay))
cursor.execute("INSERT INTO employees VALUES (:fname, :lname, :pay)", {'fname': emp3.fname, 'lname': emp3.lname, 'pay': emp3.pay})
cursor.execute("INSERT INTO employees VALUES (:fname, :lname, :pay)", {'fname': emp4.fname, 'lname': emp4.lname, 'pay': emp4.pay})
cursor.execute("select * from employees where lname='Doe'")
print(cursor.fetchall())
connection.commit()
connection.close()
[('John', 'Doe', 50000), ('George', 'Doe', 35000)]
- SQLite Shell
import sqlite3
connection = sqlite3.connect(":memory:")
connection.isolation_level = None
cursor = connection.cursor()
buffer = ""
print('>> SQLite: (Blank Line to exit)')
while True:
line = input()
if line == "":
break
buffer += line
if sqlite3.complete_statement(buffer):
try:
buffer = buffer.strip()
cursor.execute(buffer)
if buffer.lstrip().upper().startswith("SELECT"):
print(cursor.fetchall())
except sqlite3.Error as error:
print("ERROR: ", error.args[0])
buffer = ""
conection.close()
>> SQLite: (Blank Line to exit)
CREATE TABLE books (title TEXT, isbn INTEGER, pages INTEGER);
INSERT INTO books VALUES ('Book Name', 6549825563, 256);
SELECT * FROM books;
[('Book Name', 6549825563, 256)]
v7.2
CHANGES: Created GUI for Book Manager.
import tkinter as tk
from tkinter import ttk, scrolledtext, messagebox as msg
# Constants
FONT1 = ('Verdana', 10, 'bold')
FONT2 = ('Verdana', 10, 'normal')
BIO_WIDTH = 50
BIO_HEIGHT = 5
"""
GUI: main display class
"""
class GUI():
def __init__(self):
self.root = tk.Tk()
self.root.title('Book Reviewer')
self.root.resizable(False, False)
self.create_widgets()
def submit(self):
msg.showinfo('Note', 'Your review has been saved!')
def create_widgets(self):
# Create variables
self.title = tk.StringVar()
self.isbn = tk.DoubleVar()
self.pages = tk.IntVar()
self.rating = tk.IntVar()
# self.description = tk.StringVar()
# Create tabs
tabs = ttk.Notebook(self.root)
tab1 = ttk.Frame(tabs)
tab2 = ttk.Frame(tabs)
tab3 = ttk.Frame(tabs)
tabs.add(tab1, text='Tab1')
tabs.add(tab2, text='Tab2')
tabs.add(tab3, text='Tab3')
tabs.pack(expand=1, fill='both')
tabs.select(tab1)
widget1 = tk.LabelFrame(tab1, text=' Details ', font=FONT1)
widget2 = tk.LabelFrame(tab1, text=' Description ', font=FONT1)
widget1.grid(row=0, column=0, padx=10, pady=10)
widget2.grid(row=1, column=0, padx=10, pady=10)
ttk.Label(widget1, text='Book Title', font=FONT1).grid(row=0, column=0, padx=5)
ttk.Label(widget1, text='ISBN', font=FONT1).grid(row=0, column=1, padx=5)
ttk.Label(widget1, text='Pages', font=FONT1).grid(row=0, column=2, padx=5)
ttk.Label(widget1, text='Rating', font=FONT1).grid(row=0, column=3, padx=5)
self.book_title = ttk.Entry(widget1, width=30, textvariable=self.title, font=FONT2)
self.book_isbn = ttk.Entry(widget1, width=20, textvariable=self.isbn, font=FONT2)
self.book_pages = ttk.Entry(widget1, width=5, textvariable=self.pages, font=FONT2)
self.book_rating = ttk.Entry(widget1, width=3, textvariable=self.rating, font=FONT2)
self.book_description = scrolledtext.ScrolledText(widget2, width=BIO_WIDTH, height=BIO_HEIGHT, wrap=tk.WORD, font=FONT2)
self.btn_submit = tk.Button(widget2, text='Submit', command=self.submit, font=FONT1)
self.book_title.grid(row=1, column=0, padx=5, pady=10)
self.book_isbn.grid(row=1, column=1, padx=5, pady=10)
self.book_pages.grid(row=1, column=2, padx=5, pady=10)
self.book_rating.grid(row=1, column=3, padx=5, pady=10)
self.book_description.grid(row=0, column=0, padx=10, pady=10, sticky=tk.W)
self.btn_submit.grid(row=1, column=0, padx=10, pady=10, sticky=tk.N)
self.book_title.focus()
app = GUI()
app.root.mainloop()
v7.3.1
CHANGES: Created & added SQLite database functionality to the GUI.
# SQL.py
import sqlite3
"""
SQL: main database class
"""
class SQL():
def connect(self):
connection = sqlite3.connect('books.db')
cursor = connection.cursor()
return connection, cursor
def createTable(self):
connection, cursor = self.connect()
cursor.execute(""" CREATE TABLE IF NOT EXISTS books (
book_title TEXT,
book_isbn INTEGER,
book_pages INTEGER,
book_rating INTEGER,
description TEXT
)""")
connection.commit()
connection.close()
def insertBook(self, title, isbn, pages, rating, description):
connection, cursor = self.connect()
cursor.execute("INSERT INTO books VALUES (?,?,?,?,?)", (title, isbn, pages, rating, description))
connection.commit()
connection.close()
def showAllBooks(self):
connection, cursor = self.connect()
cursor.execute("SELECT * FROM books")
print(cursor.fetchall())
connection.commit()
connection.close()
if __name__ == '__main__':
sql = SQL()
import tkinter as tk
from tkinter import ttk, scrolledtext, messagebox as msg
from SQL import SQL
# Constants
FONT1 = ('Verdana', 10, 'bold')
FONT2 = ('Verdana', 10, 'normal')
BIO_WIDTH = 50
BIO_HEIGHT = 5
"""
GUI: main display class
"""
class GUI():
def __init__(self):
self.root = tk.Tk()
self.root.title('Book Reviewer')
self.root.resizable(False, False)
self.create_widgets()
self.sql = SQL()
def submit(self):
title = self.book_title.get()
isbn = self.book_isbn.get()
pages = self.book_pages.get()
rating = self.book_rating.get()
description = self.book_description.get(1.0, tk.END)
self.sql.createTable()
self.sql.insertBook(title, isbn, pages, rating, description)
msg.showinfo('Note', 'Your review has been saved!')
self.sql.showAllBooks()
def create_widgets(self):
# Create variables
self.title = tk.StringVar()
self.isbn = tk.DoubleVar()
self.pages = tk.IntVar()
self.rating = tk.IntVar()
# self.description = tk.StringVar()
# Create tabs
tabs = ttk.Notebook(self.root)
tab1 = ttk.Frame(tabs)
tab2 = ttk.Frame(tabs)
tab3 = ttk.Frame(tabs)
tabs.add(tab1, text='Tab1')
tabs.add(tab2, text='Tab2')
tabs.add(tab3, text='Tab3')
tabs.pack(expand=1, fill='both')
tabs.select(tab1)
# Tab: 1
widget1 = tk.LabelFrame(tab1, text=' Details ', font=FONT1)
widget2 = tk.LabelFrame(tab1, text=' Description ', font=FONT1)
widget1.grid(row=0, column=0, padx=10, pady=10)
widget2.grid(row=1, column=0, padx=10, pady=10)
ttk.Label(widget1, text='Book Title', font=FONT1).grid(row=0, column=0, padx=5)
ttk.Label(widget1, text='ISBN', font=FONT1).grid(row=0, column=1, padx=5)
ttk.Label(widget1, text='Pages', font=FONT1).grid(row=0, column=2, padx=5)
ttk.Label(widget1, text='Rating', font=FONT1).grid(row=0, column=3, padx=5)
self.book_title = ttk.Entry(widget1, width=30, textvariable=self.title, font=FONT2)
self.book_isbn = ttk.Entry(widget1, width=20, textvariable=self.isbn, font=FONT2)
self.book_pages = ttk.Entry(widget1, width=5, textvariable=self.pages, font=FONT2)
self.book_rating = ttk.Entry(widget1, width=3, textvariable=self.rating, font=FONT2)
self.book_description = scrolledtext.ScrolledText(widget2, width=BIO_WIDTH, height=BIO_HEIGHT, wrap=tk.WORD, font=FONT2)
self.btn_submit = tk.Button(widget2, text='Submit', command=self.submit, font=FONT1)
self.book_title.grid(row=1, column=0, padx=5, pady=10)
self.book_isbn.grid(row=1, column=1, padx=5, pady=10)
self.book_pages.grid(row=1, column=2, padx=5, pady=10)
self.book_rating.grid(row=1, column=3, padx=5, pady=10)
self.book_description.grid(row=0, column=0, padx=10, pady=10, sticky=tk.W)
self.btn_submit.grid(row=1, column=0, padx=10, pady=10, sticky=tk.N)
self.book_title.focus()
# Tab: 2
# Tab: 3
app = GUI()
app.root.mainloop()
-
Display widget-text in different languages.
-
Changing the entire GUI's language, all at once.
-
Localizing & internationalizing the GUI.
-
Agile GUI design - Callbacks module.
-
Testing
- Debugging (Default):
pdb
- Debugging (Custom): Logging results using custom debug-levels.
- Self-Test:
__main__
- Unit-Test:
unittest
- Debugging (Default):
-
Writing efficient unit-tests.
-
Debug watchpoints in ST3.
v8.1
CHANGES: Disabled database communication. Added
German
language support for labels (manual).
# languages.py
"""
I18N: language-based text display class
"""
class I18N():
def __init__(self, language):
if language == 'en':
self.langEnglish()
elif language == 'de':
self.langGerman()
else:
raise NotImplementedError('Unsupported Language!')
def langEnglish(self):
self.title = 'Book Reviewer'
# more attributes
self.LABEL_WIDGET1 = ' Details '
self.LABEL_WIDGET2 = ' Description '
self.LABEL_TITLE = 'Book Title'
self.LABEL_ISBN = 'ISBN'
self.LABEL_PAGES = 'Pages'
self.LABEL_RATING = 'Rating'
self.LABEL_SUBMIT = 'Submit'
# more attributes
def langGerman(self):
self.title = 'Buchkritiker'
self.LABEL_WIDGET1 = ' Einzelheiten '
self.LABEL_WIDGET2 = ' Beschreibung '
self.LABEL_TITLE = 'Buchtitel'
self.LABEL_ISBN = 'ISBN'
self.LABEL_PAGES = 'Seiten'
self.LABEL_RATING = 'Bewertung'
self.LABEL_SUBMIT = 'Einreichen'
# more attributes
import tkinter as tk
from tkinter import ttk, scrolledtext, messagebox as msg
from languages import I18N
# Constants
FONT1 = ('Verdana', 10, 'bold')
FONT2 = ('Verdana', 10, 'normal')
BIO_WIDTH = 50
BIO_HEIGHT = 5
"""
GUI: main display class
"""
class GUI():
def __init__(self):
self.root = tk.Tk()
self.i18n = I18N('de')
self.root.title(self.i18n.title)
self.root.resizable(False, False)
self.create_widgets()
def submit(self):
pass
def create_widgets(self):
# Create variables
self.title = tk.StringVar()
self.isbn = tk.DoubleVar()
self.pages = tk.IntVar()
self.rating = tk.IntVar()
# self.description = tk.StringVar()
# Create tabs
tabs = ttk.Notebook(self.root)
tab1 = ttk.Frame(tabs)
tab2 = ttk.Frame(tabs)
tab3 = ttk.Frame(tabs)
tabs.add(tab1, text='Tab1')
tabs.add(tab2, text='Tab2')
tabs.add(tab3, text='Tab3')
tabs.pack(expand=1, fill='both')
tabs.select(tab1)
# Tab: 1
widget1 = tk.LabelFrame(tab1, text=self.i18n.LABEL_WIDGET1, font=FONT1)
widget2 = tk.LabelFrame(tab1, text=self.i18n.LABEL_WIDGET2, font=FONT1)
widget1.grid(row=0, column=0, padx=10, pady=10)
widget2.grid(row=1, column=0, padx=10, pady=10)
ttk.Label(widget1, text=self.i18n.LABEL_TITLE, font=FONT1).grid(row=0, column=0, padx=5)
ttk.Label(widget1, text=self.i18n.LABEL_ISBN, font=FONT1).grid(row=0, column=1, padx=5)
ttk.Label(widget1, text=self.i18n.LABEL_PAGES, font=FONT1).grid(row=0, column=2, padx=5)
ttk.Label(widget1, text=self.i18n.LABEL_RATING, font=FONT1).grid(row=0, column=3, padx=5)
self.book_title = ttk.Entry(widget1, width=30, textvariable=self.title, font=FONT2)
self.book_isbn = ttk.Entry(widget1, width=20, textvariable=self.isbn, font=FONT2)
self.book_pages = ttk.Entry(widget1, width=5, textvariable=self.pages, font=FONT2)
self.book_rating = ttk.Entry(widget1, width=3, textvariable=self.rating, font=FONT2)
self.book_description = scrolledtext.ScrolledText(widget2, width=BIO_WIDTH, height=BIO_HEIGHT, wrap=tk.WORD, font=FONT2)
self.btn_submit = tk.Button(widget2, text=self.i18n.LABEL_SUBMIT, command=self.submit, font=FONT1)
self.book_title.grid(row=1, column=0, padx=5, pady=10)
self.book_isbn.grid(row=1, column=1, padx=5, pady=10)
self.book_pages.grid(row=1, column=2, padx=5, pady=10)
self.book_rating.grid(row=1, column=3, padx=5, pady=10)
self.book_description.grid(row=0, column=0, padx=10, pady=10, sticky=tk.W)
self.btn_submit.grid(row=1, column=0, padx=10, pady=10, sticky=tk.N)
self.book_title.focus()
# Tab: 2
# Tab: 3
app = GUI()
app.root.mainloop()
v8.2
CHANGES: Added
Tab2
containingAll Time-Zones
,Local TimeZone
,Time (Now)
.I18N
hasn't been extended. DEPENDENCIES: pytz, tzlocal.
import tkinter as tk
from tkinter import ttk, scrolledtext, messagebox as msg
from languages import I18N
from datetime import datetime
import pytz
from tzlocal import get_localzone
# Constants
FONT1 = ('Verdana', 10, 'bold')
FONT2 = ('Verdana', 10, 'normal')
BIO_WIDTH = 50
BIO_HEIGHT = 5
"""
GUI: main display class
"""
class GUI():
def __init__(self):
self.root = tk.Tk()
self.i18n = I18N('de')
self.root.title(self.i18n.title)
self.root.resizable(False, False)
self.create_widgets()
def submit(self):
pass
def allTimeZones(self):
self.scroll.delete('1.0', tk.END)
for timezone in pytz.all_timezones:
self.scroll.insert(tk.INSERT, timezone + '\n')
def localTimeZone(self):
self.scroll.delete('1.0', tk.END)
self.scroll.insert(tk.INSERT, get_localzone())
def nowTime(self):
time_format = "%d-%m-%Y %H:%M:%S %Z(UTC%z)"
utc = datetime.now(pytz.timezone('UTC'))
time_local = utc.astimezone(get_localzone())
self.scroll.delete('1.0', tk.END)
self.scroll.insert(tk.INSERT, time_local.strftime(time_format) + '\n')
def create_widgets(self):
# Create variables
self.title = tk.StringVar()
self.isbn = tk.DoubleVar()
self.pages = tk.IntVar()
self.rating = tk.IntVar()
# self.description = tk.StringVar()
# Create tabs
tabs = ttk.Notebook(self.root)
tab1 = ttk.Frame(tabs)
tab2 = ttk.Frame(tabs)
tab3 = ttk.Frame(tabs)
tabs.add(tab1, text='Tab1')
tabs.add(tab2, text='Tab2')
tabs.add(tab3, text='Tab3')
tabs.pack(expand=1, fill='both')
tabs.select(tab2)
# Tab: 1
widget1 = tk.LabelFrame(tab1, text=self.i18n.LABEL_WIDGET1, font=FONT1)
widget2 = tk.LabelFrame(tab1, text=self.i18n.LABEL_WIDGET2, font=FONT1)
widget1.grid(row=0, column=0, padx=10, pady=10)
widget2.grid(row=1, column=0, padx=10, pady=10)
ttk.Label(widget1, text=self.i18n.LABEL_TITLE, font=FONT1).grid(row=0, column=0, padx=5)
ttk.Label(widget1, text=self.i18n.LABEL_ISBN, font=FONT1).grid(row=0, column=1, padx=5)
ttk.Label(widget1, text=self.i18n.LABEL_PAGES, font=FONT1).grid(row=0, column=2, padx=5)
ttk.Label(widget1, text=self.i18n.LABEL_RATING, font=FONT1).grid(row=0, column=3, padx=5)
self.book_title = ttk.Entry(widget1, width=30, textvariable=self.title, font=FONT2)
self.book_isbn = ttk.Entry(widget1, width=20, textvariable=self.isbn, font=FONT2)
self.book_pages = ttk.Entry(widget1, width=5, textvariable=self.pages, font=FONT2)
self.book_rating = ttk.Entry(widget1, width=3, textvariable=self.rating, font=FONT2)
self.book_description = scrolledtext.ScrolledText(widget2, width=BIO_WIDTH, height=BIO_HEIGHT, wrap=tk.WORD, font=FONT2)
self.btn_submit = tk.Button(widget2, text=self.i18n.LABEL_SUBMIT, command=self.submit, font=FONT1)
self.book_title.grid(row=1, column=0, padx=5, pady=10)
self.book_isbn.grid(row=1, column=1, padx=5, pady=10)
self.book_pages.grid(row=1, column=2, padx=5, pady=10)
self.book_rating.grid(row=1, column=3, padx=5, pady=10)
self.book_description.grid(row=0, column=0, padx=10, pady=10, sticky=tk.W)
self.btn_submit.grid(row=1, column=0, padx=10, pady=10, sticky=tk.N)
self.book_title.focus()
# Tab: 2
self.timezone_all = tk.Button(tab2, text='All Time-Zones', font=FONT1, command=self.allTimeZones)
self.timezone_local = tk.Button(tab2, text='Local Time-Zone', font=FONT1, command=self.localTimeZone)
self.time_now = tk.Button(tab2, text='Time (Now)', font=FONT1, command=self.nowTime)
self.scroll = scrolledtext.ScrolledText(tab2, width=BIO_WIDTH // 5 * 2, height=BIO_HEIGHT * 5, wrap=tk.WORD, font=FONT2)
self.timezone_all.grid(row=0, column=0, padx=5)
self.timezone_local.grid(row=0, column=1, padx=5)
self.time_now.grid(row=0, column=2, padx=5)
self.scroll.grid(row=1, column=1, padx=10, pady=10)
# Tab: 3
app = GUI()
app.root.mainloop()
- Pick a fixed window size & resize all images to window (eg. Windows PhtotoViewer).
- Allow window to open in split-screen. Useful when reviewing images while working on them. One way to do this is
root.resizable(True, True)
. - Display GIF recordings. Current only first frame of GIF is displayed.
- Using
pdftopng
, generate images, and play them in slideshow.
v1.1
# Following Previous scheme: Class inherits from none.
import tkinter as tk
from PIL import ImageTk
from itertools import cycle
import os
class SlideShow():
def __init__(self, duration=1000):
self.root = tk.Tk()
self.root.resizable(True, False)
self.duration = duration
slides = [slide for slide in os.listdir()
if slide.endswith('gif')
or slide.endswith('jpg')
or slide.endswith('png')]
self.slide_cycle = cycle((ImageTk.PhotoImage(file=slide), slide) for slide in slides)
self.slide_label = tk.Label(self.root)
self.slide_label.pack()
def slide_callback(self):
slide_current, slide_name = next(self.slide_cycle)
self.slide_label.config(image=slide_current)
self.root.title(slide_name)
self.root.after(self.duration, self.slide_callback)
app = SlideShow()
app.root.after(0, app.slide_callback)
app.root.mainloop()
v1.2
# From Book: Class inherits from `Tk`
from tkinter import Tk, Label
from PIL import ImageTk
from itertools import cycle
import os
class SlideShow(Tk):
def __init__(self, duration=1000):
Tk.__init__(self)
self.duration = duration
slides = [slide for slide in os.listdir()
if slide.endswith('gif')
or slide.endswith('jpg')
or slide.endswith('png')]
self.slide_cycle = cycle((ImageTk.PhotoImage(file=slide), slide) for slide in slides)
self.slide_label = Label(self)
self.slide_label.pack()
def slide_callback(self):
slide_current, slide_name = next(self.slide_cycle)
self.slide_label.config(image=slide_current)
self.title(slide_name)
self.after(self.duration, self.slide_callback)
root = SlideShow()
root.resizable(False, False)
root.after(0, root.slide_callback)
root.mainloop()
- BlackJack is a card game where the aim is to get as close to 21 points as possible. If you go over, you are out.
- Number cards are worth their face value, Picture cards are worth 10, and an Ace is worth either 1 or 11 (1, if adding 11 to the total value of the cards in hand takes it beyond 21). Players are initially dealt two cards and can either choose to hit (receive another card) or stick (submit their current hand).
- Players face off against the dealer, who has one card face down and one face up. When all players have chosen to stick or are out (having a hand over 21), the winner is the one with a hand closest to 21.
v1
CHANGES: CLI Version.
- Classes - Card, Deck, Hand, Game. A deck initializes 52 cards. A hand receives cards dealt from a shuffled deck.
import random
# import subprocess
class Card:
def __init__(self, suit, value):
self.suit = suit
self.value = value
def __repr__(self):
return '{} of {}'.format(self.value, self.suit)
class Deck:
def __init__(self):
self.cards = [Card(suit, value)
for suit in ['Spades', 'Clubs', 'Hearts', 'Diamonds']
for value in ['A', '2', '3', '4', '5', '6', '7', '8', '9', '10', 'J', 'Q', 'K']
]
def shuffle(self):
if len(self.cards) > 1:
random.shuffle(self.cards)
def deal(self):
if len(self.cards) > 1:
return self.cards.pop(0)
class Hand:
def __init__(self, dealer=False):
self.dealer = dealer
self.cards = []
self.value = 0
def add_card(self, card):
self.cards.append(card)
def calculate_value(self):
self.value = 0
hasAce = False
for card in self.cards:
if card.value.isnumeric():
self.value += int(card.value)
else:
if card.value == 'A':
hasAce = True
self.value += 11
else:
self.value += 10
if hasAce and self.value > 21:
self.value -= 10
return self.value
def display(self):
if self.dealer:
print('HIDDEN,', self.cards[1])
else:
for card in self.cards:
print(card, end=', ')
print('Value:', self.calculate_value())
class Game:
def __init__(self):
playing = True
while playing:
self.deck = Deck()
self.deck.shuffle()
self.player_hand = Hand()
self.dealer_hand = Hand(dealer=True)
for i in range(2):
self.player_hand.add_card(self.deck.deal())
self.dealer_hand.add_card(self.deck.deal())
print('>> Your Hand: ')
self.player_hand.display()
print('>> Dealer\'s Hand: ')
self.dealer_hand.display()
game_over = False
while not game_over:
player_hasBlackjack, dealer_hasBlackjack = self.check_ifBlackjack()
if player_hasBlackjack or dealer_hasBlackjack:
game_over = True
self.show_results(player_hasBlackjack, dealer_hasBlackjack)
continue
choice = input('Please Choose (Hit/Stick): ').lower()
while choice not in ['h', 'hit', 's', 'stick']:
choice = input('Please Choose (Hit/Stick): ').lower()
if choice in ['h', 'hit']:
self.player_hand.add_card(self.deck.deal())
print('>> Your Hand: ')
self.player_hand.display()
if self.player_isOver():
print('You have lost!')
game_over = True
else:
player_hand_value = self.player_hand.calculate_value()
dealer_hand_value = self.dealer_hand.calculate_value()
print('>> Your Hand:', player_hand_value)
print('>> Dealer\'s Hand:', dealer_hand_value)
if player_hand_value > dealer_hand_value:
print('You have won!')
elif player_hand_value == dealer_hand_value:
print('We have a tie!')
else:
print('You have lost!')
game_over = True
again = input('Play Again? (Yes/No):').lower()
while again not in ['y', 'yes', 'n', 'no']:
again = input('Play Again? (Yes/No):').lower()
if again in ['n', 'no']:
print('Thanks for playing!')
playing = False
else:
# subprocess.run('cls', shell=True)
game_over = False
def player_isOver(self):
return self.player_hand.calculate_value() > 21
def check_ifBlackjack(self):
player, dealer = False, False
if self.player_hand.calculate_value() == 21:
player = True
if self.dealer_hand.calculate_value() == 21:
dealer = True
return player, dealer
def show_results(self, player_hasBlackjack, dealer_hasBlackjack):
if player_hasBlackjack and dealer_hasBlackjack:
print('Both players have BlackJack; It\'s a tie!')
elif player_hasBlackjack:
print('You have BlackJack; You have won!')
else:
print('Dealer has BlackJack; You have lost!')
if __name__ == '__main__':
# subprocess.run('cls', shell=True)
app = Game()
v2.1
CHANGES: GUI Version (No Sound).
- Convert CLI to GUI.
- Insert cards. Obtained from here.
- Resize card images to fit window. Resized using
magick mogrify -resize 120x165 *.png
.
import os
import tkinter as tk
import random
# Global Definitions
FONT1 = ('CMU Sans Serif', 32, 'bold')
FONT2 = ('CMU Sans Serif', 50, 'bold')
RESOURCES = os.path.abspath(os.path.join(os.path.dirname(__file__), 'resources/PRJ02/'))
class Card:
def __init__(self, suit, value):
self.suit = suit
self.value = value
self.img = tk.PhotoImage(file=RESOURCES + '\\' + self.suit + self.value + '.png')
def __repr__(self):
return '{} of {}'.format(self.value, self.suit)
def get_file(self):
return self.img
@classmethod
def get_backOfCard(cls):
cls.back = tk.PhotoImage(file=RESOURCES + '\\back.png')
return cls.back
class Deck:
def __init__(self):
self.cards = [Card(suit, value)
for suit in ['Spades', 'Clubs', 'Hearts', 'Diamonds']
for value in ['A', '2', '3', '4', '5', '6', '7', '8', '9', '10', 'J', 'Q', 'K']
]
def shuffle(self):
if len(self.cards) > 1:
random.shuffle(self.cards)
def deal(self):
if len(self.cards) > 1:
return self.cards.pop(0)
class Hand:
def __init__(self, dealer=False):
self.dealer = dealer
self.cards = []
self.value = 0
def add_card(self, card):
self.cards.append(card)
def calculate_value(self):
self.value = 0
hasAce = False
for card in self.cards:
if card.value.isnumeric():
self.value += int(card.value)
else:
if card.value == 'A':
hasAce = True
self.value += 11
else:
self.value += 10
if hasAce and self.value > 21:
self.value -= 10
return self.value
class GameState:
def __init__(self):
self.deck = Deck()
self.deck.shuffle()
self.player_hand = Hand()
self.dealer_hand = Hand(dealer=True)
for i in range(2):
self.player_hand.add_card(self.deck.deal())
self.dealer_hand.add_card(self.deck.deal())
self.hasWinner = ''
def someone_hasBlackjack(self):
player, dealer = False, False
if self.player_hand.calculate_value() == 21:
player = True
if self.dealer_hand.calculate_value() == 21:
dealer = True
if player and dealer:
return 'dp'
elif player:
return 'p'
elif dealer:
return 'd'
return False
def hit(self):
self.player_hand.add_card(self.deck.deal())
if self.someone_hasBlackjack() == 'p':
self.hasWinner = 'p'
if self.player_isOver:
self.hasWinner = 'd'
return self.hasWinner
def get_tableState(self):
blackjack = False
winner = self.hasWinner
if not winner:
winner = self.someone_hasBlackjack()
if winner:
blackjack = True
tableState = {
'player_cards': self.player_hand.cards,
'dealer_cards': self.dealer_hand.cards,
'hasWinner': winner,
'blackjack': blackjack
}
return tableState
def get_finaltableState(self):
player_hand_value = self.player_hand.calculate_value()
dealer_hand_value = self.dealer_hand.calculate_value()
if player_hand_value == dealer_hand_value:
winner = 'dp'
elif player_hand_value > dealer_hand_value:
winner = 'p'
else:
winner = 'd'
tableState = {
'player_cards': self.player_hand.cards,
'dealer_cards': self.dealer_hand.cards,
'hasWinner': winner
}
return tableState
def get_playerScore(self):
return 'Score: ' + str(self.player_hand.calculate_value())
def player_isOver(self):
return self.player_hand.calculate_value() > 21
class GameScreen(tk.Tk):
def __init__(self):
tk.Tk.__init__(self)
self.title('BlackJack')
self.geometry('1280x720')
self.resizable(False, False)
# Define: Instance Constants
self.CARD_ORIGINAL_POSITION = 100
self.CARD_WIDTH_OFFSET = 120
self.PLAYER_CARD_HEIGHT = 350
self.DEALER_CARD_HEIGHT = 150
self.PLAYER_SCORE_COORDINATES = (500, 500)
self.WINNER_SCORE_COORDINATES = (640, 300)
# Define: Game Attributes - GameState, GameScreen
self.game_state = GameState()
self.game_screen = tk.Canvas(self, bg='#FFFFFF', width=1280, height=600)
self.bottom_frame = tk.Frame(self, width=1280, height=120, bg='#C0C0C0')
self.bottom_frame.pack_propagate(0)
# Frame Widgets
self.btn_hit = tk.Button(self.bottom_frame, text='Hit', width=10, font=FONT1, command=self.hit)
self.btn_stick = tk.Button(self.bottom_frame, text='Stick', width=10, font=FONT1, command=self.stick)
self.btn_playAgain = tk.Button(self.bottom_frame, text='Play Again', width=10, font=FONT1, command=self.playAgain)
self.btn_quit = tk.Button(self.bottom_frame, text='Quit', width=10, font=FONT1, command=self.quit)
self.btn_hit.pack(side=tk.LEFT)
self.btn_stick.pack(side=tk.RIGHT)
self.bottom_frame.pack(side=tk.BOTTOM, fill=tk.X)
self.game_screen.pack(side=tk.LEFT, anchor=tk.N)
self.display_table()
def display_table(self, hide_dealer=True, tableState=None):
if not tableState:
tableState = self.game_state.get_tableState()
player_cardImages = [card.get_file() for card in tableState['player_cards']]
dealer_cardImages = [card.get_file() for card in tableState['dealer_cards']]
if hide_dealer and not tableState['blackjack']:
dealer_cardImages[0] = Card.get_backOfCard()
self.game_screen.delete('all')
self.tabletop_image = tk.PhotoImage(file=RESOURCES + '\\tabletop.png')
self.game_screen.create_image((640, 300), image=self.tabletop_image)
for card_number, card_image in enumerate(player_cardImages):
self.game_screen.create_image(self.CARD_ORIGINAL_POSITION + self.CARD_WIDTH_OFFSET * card_number,
self.PLAYER_CARD_HEIGHT, image=card_image)
for card_number, card_image in enumerate(dealer_cardImages):
self.game_screen.create_image(self.CARD_ORIGINAL_POSITION + self.CARD_WIDTH_OFFSET * card_number,
self.DEALER_CARD_HEIGHT, image=card_image)
# Display Score
self.game_screen.create_text(self.PLAYER_SCORE_COORDINATES, text=self.game_state.get_playerScore(), font=FONT1)
if tableState['hasWinner']:
if tableState['hasWinner'] == 'p':
self.game_screen.create_text(self.WINNER_SCORE_COORDINATES, text='You Win!', fill='#FF0000', font=FONT2)
elif tableState['hasWinner'] == 'dp':
self.game_screen.create_text(self.WINNER_SCORE_COORDINATES, text='Tie!', fill='#FF0000', font=FONT2)
else:
self.game_screen.create_text(self.WINNER_SCORE_COORDINATES, text='Dealer Wins!', fill='#FF0000', font=FONT2)
self.show_playAgain_options()
def show_playAgain_options(self):
self.btn_hit.pack_forget()
self.btn_stick.pack_forget()
self.btn_playAgain.pack(side=tk.LEFT)
self.btn_quit.pack(side=tk.RIGHT)
def show_gameplay_buttons(self):
self.btn_hit.pack(side=tk.LEFT)
self.btn_stick.pack(side=tk.RIGHT)
self.btn_playAgain.pack_forget()
self.btn_quit.pack_forget()
def playAgain(self):
self.show_gameplay_buttons()
self.game_state = GameState()
self.display_table()
def hit(self):
self.game_state.hit()
self.display_table()
def stick(self):
tableState = self.game_state.get_finaltableState()
self.display_table(False, tableState)
if __name__ == '__main__':
app = GameScreen()
app.mainloop()
v2.2
CHANGES: Added betting options & audio to GUI.
- Generate animations on canvas.
- Control GUI when animation is playing.
- Insert sounds using
pygame
module. Obtained from here. - Insert link to video. Added using
[![alt_text](img_link)](video_link)
.
INFO
GameWindow
: manages our app's main window & widgets.GameScreen
: contains all logic for the window's graphics & animations.GameState
: contains all logic for the actual game. Represents various stages of the game.
super.__init__(self, master, **kwargs)
What is master?
What is Python REPL (pg. 119)?
List multiplication: ( [10]*6 + [-10]*6 ) * 7
[10, 10, 10, 10, 10, 10,
-10, -10, -10, -10, -10, -10,
10, 10, 10, 10, 10, 10,
-10, -10, -10, -10, -10, -10,
10, 10, 10, 10, 10, 10,
-10, -10, -10, -10, -10, -10,
10, 10, 10, 10, 10, 10,
-10, -10, -10, -10, -10, -10,
10, 10, 10, 10, 10, 10,
-10, -10, -10, -10, -10, -10,
10, 10, 10, 10, 10, 10,
-10, -10, -10, -10, -10, -10,
10, 10, 10, 10, 10, 10,
-10, -10, -10, -10, -10, -10]
v1.1
CHANGES: Basic Editor.
import tkinter as tk
from tkinter import ttk
# Constants
FONT = ('Consolas', 10, 'normal')
class TextArea(tk.Text):
def __init__(self, master, **kwargs):
super().__init__(**kwargs)
self.master = master
self.config(wrap=tk.WORD)
class MainWindow(tk.Tk):
def __init__(self):
super().__init__()
self.scrollbar = ttk.Scrollbar(orient='vertical', command=self.scroll_text)
self.text_area = TextArea(self, bg='white', fg='black', font=FONT, undo=True)
self.text_area.configure(yscrollcommand=self.scrollbar.set)
self.scrollbar.pack(side=tk.RIGHT, fill=tk.Y)
self.text_area.pack(side=tk.LEFT, fill=tk.BOTH, expand=1)
def scroll_text(self, *args):
self.text_area.yview_moveto(args[1])
if __name__ == '__main__':
root = MainWindow()
root.title('NoteTaker')
root.mainloop()
v1.2
CHANGES: Basic Editor.
TkDocs: Python Tutorial
tkinter: 8.5 Reference (Shipman)
tkinter: Python Resources
tkinter: Python Standard Library
Should your GUI inherit from tk.Tk
or tk.Frame
? Should it inherit from anything at all? *
A simple GUI can be created using either of these scripts.
# 1: Class inherits from nothing. (Actually, it inherits from Python's default `Object`.)
import tkinter as tk
class GUI():
def __init__(self):
self.root = tk.Tk()
self.root.title('Python GUI')
self.create_widgets()
def quit(self):
self.master.quit()
def create_widgets(self):
self.btn_quit = tk.Button(self.root, text='Quit', command=self.quit)
self.btn_quit.grid(row=0, column=0)
app = GUI()
app.root.mainloop()
# 2: Class inherits from `Tk`.
import tkinter as tk
class GUI(tk.Tk):
def __init__(self, master=None):
super().__init__(self, master)
self.create_widgets()
def quit(self):
self.master.quit()
def create_widgets(self):
self.btn_quit = tk.Button(self, text='Quit', command=self.quit)
self.btn_quit.grid(row=0, column=0)
app = GUI()
app.title('Python GUI')
app.mainloop()
# 3: Class inherits from `Frame`.
import tkinter as tk
class GUI(tk.Frame):
def __init__(self, master=None):
super().__init__(self, master)
self.grid()
self.create_widgets()
def quit(self):
self.master.quit()
def create_widgets(self):
self.btn_quit = tk.Button(self, text='Quit', command=self.quit)
self.btn_quit.grid(row=0, column=0)
app = GUI()
app.master.title('Python GUI')
app.mainloop()
1
is created in a conservative style, where the whole window is controlled through an attribute (root
) of the particular instance (app
). This could be more memory-intensive, as it adds another level of heirarchy to the code-structure.
2
& 3
create the app
instance from a class (GUI
) that itself inherits from a parent class (Tk
or Frame
). There is no need to declare a root
attribute-object in both these cases since any class instance is in fact, the whole window.
One slight advantage inheriting from Frame
has over Tk
is when you want your application to support multiple identical windows. In that case, inheriting from Frame
lets you create subsequent windows as children of instances of Toplevel
.
So, avoid 1
. Use 2
or 3
instead.
Widgets - tk
or ttk
? *
themed tk (ttk
) widgets have a native-OS feel. tk
widgets have a consistent look on all platforms. So, if a have a fixed style in mind that you want to apply to the widget, go with tk
, otherwise ttk
would appeal more to the user.