Tuesday, April 22, 2025

Tkinter - Scale

This source will produce simple Tkinter GUI with horizontal scale on it, in value range from 1 to 100, using label "Range". 

Scale will be packed to center of the top_win. At the bottom of the scale we will have submit Button. 

No functions at the moment, just GUI:

from tkinter import *
import tkinter.messagebox as mb
import os

top_win = Tk()
top_win.geometry("800x800")

scale = Scale(top_win, label = "Range", from_ = 1, to = 100,
              orient = HORIZONTAL)
scale.pack(anchor = CENTER)

btn_1 = Button(top_win, text = "Submit")
btn_1.pack(anchor = CENTER)

top_win.mainloop()

So, a source to create scale is this one:

scale = Scale(top_win, label = "Range", from_ = 1, to = 100,
              orient = HORIZONTAL)
scale.pack(anchor = CENTER)

What about a source with function that will print something on Python Shell based on values from Scale:

from tkinter import *
import tkinter.messagebox as mb
import os

top_win = Tk()
top_win.geometry("800x800")

def select():
    selected = real_val.get()
    print("Selected From Range: ", selected)

    if selected >= 50:
        print("More Than 50")

real_val = IntVar()

scale = Scale(top_win, label = "Range", length = 200, from_ = 1, to = 100,
              orient = HORIZONTAL, troughcolor = "red", variable = real_val)
scale.pack(anchor = CENTER)

btn_1 = Button(top_win, text = "Submit", command = select)
btn_1.pack(anchor = CENTER)

top_win.mainloop()

Function select() will get and check a point from scale. That value will be printed in Python Shell.

Also, if value is higher than 50, that will be printed too.

def select():
    selected = real_val.get()
    print("Selected From Range: ", selected)

    if selected >= 50:
        print("More Than 50")

Value is stored in real_val using this line:

real_val = IntVar()

To connect scale with real_val, use these lines:

scale = Scale(top_win, label = "Range", length = 200, from_ = 1, to = 100,
              orient = HORIZONTAL, troughcolor = "red", variable = real_val)
scale.pack(anchor = CENTER)

At the end we need to connect a button with function, using "command = ":

btn_1 = Button(top_win, text = "Submit", command = select)
btn_1.pack(anchor = CENTER)

There is corresponding YouTube tutorial on Tkinter Scale.

Tkinter - Menubar and Menus

Time to talk about horizontal menubar. We will have options to ping Google and Yahoo, using os module.

Simple functions that will do pinging:

def pg():
    os.system("ping google.com")

def py():
    os.system("ping yahoo.com")

 Menu will be created in top_win:

bar = Menu(top_win)

Time to add buttons that will be connected to corresponding functions:

bar.add_command(label = "Ping Google", command = pg)
bar.add_command(label = "Ping Yahoo", command = py)

 But also we need to activate menu in top_win, before mainloop:

top_win.config(menu = bar)

This is full working source: 

from tkinter import *
import tkinter.messagebox as mb
import os

top_win = Tk()
top_win.geometry("800x800")

def pg():
    os.system("ping google.com")

def py():
    os.system("ping yahoo.com")

bar = Menu(top_win)

bar.add_command(label = "Ping Google", command = pg)
bar.add_command(label = "Ping Yahoo", command = py)

top_win.config(menu = bar)
top_win.mainloop()

We can also have menu which is found in most of the editors. Make sure that this source is working on your machine.

Once you run it, what is clicked will be printed in Python Shell. This is just a simple presentation how to connect buttons to vertical menus. In real life scenario our functions will be probably more advanced than printing stuff on screen.

from tkinter import *
import tkinter.messagebox as mb
import os

top_win = Tk()
top_win.geometry("800x800")

bar = Menu(top_win)

def new():
    print("New Clicked")
def open_file():
    print("Open File Clicked")

file = Menu(bar)
file.add_command(label = "New", command = new)
file.add_command(label = "Open", command = open_file)
file.add_command(label = "Save")
file.add_command(label = "Save As")
file.add_command(label = "Close")
file.add_command(label = "Exit")

bar.add_cascade(label = "File", menu = file)

top_win.config(menu = bar)
top_win.mainloop()

There is also YouTube tutorial on how to create Menubar and Menus with Tkinter

Tkinter - Radiobuttons

Radiobuttons are easy, just as Checkbuttons. First, make sure that this simple source is working, and then we will explain:

from tkinter import *
import tkinter.messagebox as mb
import os

top_win = Tk()
top_win.geometry("800x800")

lab_1 = Label(top_win, text = "Select only one: ").pack(anchor = W)

real_stuff = IntVar()

rad_1 = Radiobutton(top_win, text = "Python", variable = real_stuff, value = 1)
rad_1.pack(anchor = W)

rad_2 = Radiobutton(top_win, text = "C++", variable = real_stuff, value = 2)
rad_2.pack(anchor = W)

rad_3 = Radiobutton(top_win, text = "Perl", variable = real_stuff, value = 3)
rad_3.pack(anchor = W)

top_win.mainloop()

To explain what needs to be done we will have Tkinter label:

lab_1 = Label(top_win, text = "Select only one: ").pack(anchor = W)

Place that will hold choice will be real_stuff:

real_stuff = IntVar()

Then we will have 3 radiobuttons, where all of them will point to real_stuff. Radio buttons will have dedicated value: 1, 2 and 3. This is important:

rad_1 = Radiobutton(top_win, text = "Python", variable = real_stuff, value = 1)
rad_1.pack(anchor = W)

rad_2 = Radiobutton(top_win, text = "C++", variable = real_stuff, value = 2)
rad_2.pack(anchor = W)

rad_3 = Radiobutton(top_win, text = "Perl", variable = real_stuff, value = 3)
rad_3.pack(anchor = W)

What about function that will process values ? Again, make sure that code works, and then we will explain: 

from tkinter import *
import tkinter.messagebox as mb
import os

top_win = Tk()
top_win.geometry("800x800")

def selected():
    selected = real_stuff.get()

    output.config(text = selected)

    if selected == 1:
        print("Selected: Python at position", selected)
    if selected == 2:
        print("Selected: C++ at position", selected)
    if selected == 3:
        print("Selected: Perl at position", selected)

lab_1 = Label(top_win, text = "Select only one: ").pack(anchor = W)

real_stuff = IntVar()

rad_1 = Radiobutton(top_win, text = "Python", variable = real_stuff,
                    value = 1, command = selected)
rad_1.pack(anchor = W)

rad_2 = Radiobutton(top_win, text = "C++", variable = real_stuff, value = 2,
                    command = selected)
rad_2.pack(anchor = W)

rad_3 = Radiobutton(top_win, text = "Perl", variable = real_stuff, value = 3,
                    command = selected)
rad_3.pack(anchor = W)

output = Label(top_win, text = "You Selected: ")
output.pack(anchor = W)

top_win.mainloop()

Function selected() will get values from real_stuff using get() method.

Then it will set what is captured as config text for output. Output is external Label where results will be printed, in Tkinter Window.

Also, based on choice, values will be printed in Python Shell using if checks: 

def selected():
    selected = real_stuff.get()

    output.config(text = selected)

    if selected == 1:
        print("Selected: Python at position", selected)
    if selected == 2:
        print("Selected: C++ at position", selected)
    if selected == 3:
        print("Selected: Perl at position", selected)

All radio buttons now have connection to function using "command = ":

rad_1 = Radiobutton(top_win, text = "Python", variable = real_stuff,
                    value = 1, command = selected)
rad_1.pack(anchor = W)

rad_2 = Radiobutton(top_win, text = "C++", variable = real_stuff, value = 2,
                    command = selected)
rad_2.pack(anchor = W)

rad_3 = Radiobutton(top_win, text = "Perl", variable = real_stuff, value = 3,
                    command = selected)
rad_3.pack(anchor = W)

And this is source for output Label:

output = Label(top_win, text = "You Selected: ")
output.pack(anchor = W)

As always, you have corresponding YT tutorial on Tkinter Radiobuttnos.

Tkinter - Checkbuttons

This tutorial will be about Tkinter Checkbuttons. First, make sure that you can run this code, and than we will explain it:

from tkinter import *
import tkinter.messagebox as mb
import os

top_win = Tk()
top_win.geometry("800x800")

gen_lab  = Label(top_win, text = "Engine Boost")
gen_lab.grid(row = 0, column = 0)

turbo_10 = IntVar()
turbo_20 = IntVar()

ch_10 = Checkbutton(top_win, text = "Boost +10", variable = turbo_10)
ch_10.grid(row = 1, column = 0)

ch_20 = Checkbutton(top_win, text = "Boost +20", variable = turbo_20)
ch_20.grid(row = 2, column = 0)

but_1 = Button(top_win, text = "Activate Boost")
but_1.grid(row = 3, column = 0)
top_win.mainloop()

Just as with Listbox Widget, we will need Labels for Checkbuttons:

gen_lab  = Label(top_win, text = "Engine Boost")
gen_lab.grid(row = 0, column = 0)

And than we will need 2 variables that will be used to hold values:

turbo_10 = IntVar()
turbo_20 = IntVar()

Now we need 2 Checkbuttons. Please note variable = that is connected to corresponding variables. Checkbuttons, as other Tkinter widgets must be positioned. In this case with grid option: 

ch_10 = Checkbutton(top_win, text = "Boost +10", variable = turbo_10)
ch_10.grid(row = 1, column = 0)

ch_20 = Checkbutton(top_win, text = "Boost +20", variable = turbo_20)
ch_20.grid(row = 2, column = 0)

And of course, submit button: 

but_1 = Button(top_win, text = "Activate Boost")
but_1.grid(row = 3, column = 0)

So far, so good.

Custom functions for Tkinter Checkbuttons

Make sure that you can run this code, and then we will explain it. You will see results in Python Shell:

from tkinter import *
import tkinter.messagebox as mb
import os

top_win = Tk()
top_win.geometry("800x800")

def activate_boost():
    status_10 = turbo_10.get()
    status_20 = turbo_20.get()

    if status_10 == 1:
        print("Boost +10 Activated")
    if status_20 == 1:
        print("Boost +20 Activated")
    if status_10 == 1 and status_20 == 1:
        print("!" * 50)
        print("ALERT - DANGER")
        print("Lower Down Boost Levels - Just One Checkbutton")
    if status_10 == 0 and status_20 == 0:
        print("Normal Operation")

gen_lab  = Label(top_win, text = "Engine Boost")
gen_lab.grid(row = 0, column = 0)

turbo_10 = IntVar()
turbo_20 = IntVar()

ch_10 = Checkbutton(top_win, text = "Boost +10", variable = turbo_10)
ch_10.grid(row = 1, column = 0)

ch_20 = Checkbutton(top_win, text = "Boost +20", variable = turbo_20)
ch_20.grid(row = 2, column = 0)

but_1 = Button(top_win, text = "Activate Boost", command = activate_boost)
but_1.grid(row = 3, column = 0)
top_win.mainloop()

This is our custom function that will process what is checked:

def activate_boost():
    status_10 = turbo_10.get()
    status_20 = turbo_20.get()

    if status_10 == 1:
        print("Boost +10 Activated")
    if status_20 == 1:
        print("Boost +20 Activated")
    if status_10 == 1 and status_20 == 1:
        print("!" * 50)
        print("ALERT - DANGER")
        print("Lower Down Boost Levels - Just One Checkbutton")
    if status_10 == 0 and status_20 == 0:
        print("Normal Operation")

With status_10 and status_20 we will get choice. Then we are checking if only one status is set to 1, and printing appropriate text.

If both of statuses are 1, than we print a message: "Lower Down Boost Levels - Just One Checkbutton".

If both statuses are 0, which means they are not operational, than some imaginary machine is working in a normal mode, no any boost, and we are printing "Normal operation".

You are strongly advised to check corresponding YT tutorial on Checkbuttons.

Tkinter - Listbox

It's easy to create listboxes using Tkinter. In most cases having label for that list will be helpful, so let's create it and we will use grid option for positioning:

gen_lab = Label(top_win, text = "Domain")
gen_lab.grid(row = 0, column = 0)

Ok, now we will set Listbox that will deal with, for example, domain names. That listbox will be in top_win, as with all Tkinter widgets in most simple cases:

list_domains = Listbox(top_win)

Once we have it, we can populate a list with values using insert() method, stating item position in a list, and corresponding values:

list_domains.insert(1, "google.com")
list_domains.insert(2, "yahoo.com")
list_domains.insert(3, "bing.com")

Now it's the time to grid Listbox:

list_domains.grid(row = 1, column = 0)

And this is full working source with that simple list. No operations at the moment, but list is fine:

from tkinter import *
import tkinter.messagebox as mb
import os

top_win = Tk()
top_win.geometry("800x800")

gen_lab = Label(top_win, text = "Domain")
gen_lab.grid(row = 0, column = 0)

list_domains = Listbox(top_win)

list_domains.insert(1, "google.com")
list_domains.insert(2, "yahoo.com")
list_domains.insert(3, "bing.com")

list_domains.grid(row = 1, column = 0)
top_win.mainloop()

Now we will create function that will delete selected domain from a list. We are using curselection() method for item selection, and delete() method to remove selected item:

def delete_from_list():
    selected = list_domains.curselection()
    list_domains.delete(selected)

Function will be activated on button press:

but_1 = Button(top_win, text = "Delete From List", command = delete_from_list)
but_1.grid(row = 3, column = 0)

You are advised to check corresponding YT tutorial on Listbox:

This is full working script: 

from tkinter import *
import tkinter.messagebox as mb
import os

top_win = Tk()
top_win.geometry("800x800")

def delete_from_list():
    selected = list_domains.curselection()
    list_domains.delete(selected)

gen_lab = Label(top_win, text = "Domain")
gen_lab.grid(row = 0, column = 0)

list_domains = Listbox(top_win)

list_domains.insert(1, "google.com")
list_domains.insert(2, "yahoo.com")
list_domains.insert(3, "bing.com")

but_1 = Button(top_win, text = "Delete From List", command = delete_from_list)
but_1.grid(row = 3, column = 0)

list_domains.grid(row = 1, column = 0)
top_win.mainloop()


Tkinter - Frames

Think about Tkinter Frames as boxes that will help you to organize other Tkinter widgets. 

First, make sure that you can run this script on your system, and than we will analyze it:

from tkinter import *
import tkinter.messagebox as mb
import os

top_win = Tk()
top_win.geometry("800x800")

frm_1 = Frame(top_win, highlightbackground = "black", highlightthickness = 1)
frm_2 = Frame(top_win, highlightbackground = "black", highlightthickness = 1)

lab_name = Label(frm_1, text = "Name").grid(row = 0, column = 0)
lab_last_name = Label(frm_1, text = "LastName").grid(row = 1, column = 0)

ent_name = Entry(frm_1)
ent_name.grid(row = 0, column = 1)
ent_last_name = Entry(frm_1)
ent_last_name.grid(row = 1, column = 1)

but_1 = Button(frm_1, text = "Submit").grid(row = 3, column = 0)

lab_age = Label(frm_2, text = "Age").grid(row = 0, column = 0)
lab_pay = Label(frm_2, text = "Pay").grid(row = 1, column = 0)

ent_age = Entry(frm_2)
ent_age.grid(row = 0, column = 1)
ent_pay = Entry(frm_2)
ent_pay.grid(row = 1, column = 1)

but_2 = Button(frm_2, text = "Submit").grid(row = 3, column = 0)

frm_1.grid(row = 0, column = 0)
frm_2.grid(row = 0, column = 1)

top_win.mainloop()

Ok, to create Frame we must (as with other Tkinter widgets) place it into some window. In this case primary window will be top_win, with geometry 800 x 800.


To create a border around Frame we will say highlightthickness = 1, we can also set background color:

frm_1 = Frame(top_win, highlightbackground = "black", highlightthickness = 1)
frm_2 = Frame(top_win, highlightbackground = "black", highlightthickness = 1)

Then we will have Labels inside Frames:

lab_name = Label(frm_1, text = "Name").grid(row = 0, column = 0)
lab_last_name = Label(frm_1, text = "LastName").grid(row = 1, column = 0)

Having just labels is not enough, there's need for entry fields:

ent_name = Entry(frm_1)
ent_name.grid(row = 0, column = 1)
ent_last_name = Entry(frm_1)
ent_last_name.grid(row = 1, column = 1)

Submit button is also needed:

but_1 = Button(frm_1, text = "Submit").grid(row = 3, column = 0)

Now, what about Frame 2 where we will have another labels with corresponding fields:

lab_age = Label(frm_2, text = "Age").grid(row = 0, column = 0)
lab_pay = Label(frm_2, text = "Pay").grid(row = 1, column = 0)

And than entry fields for age and pay values:

ent_age = Entry(frm_2)
ent_age.grid(row = 0, column = 1)
ent_pay = Entry(frm_2)
ent_pay.grid(row = 1, column = 1)

Button in second frame will be positioned using grid values:

but_2 = Button(frm_2, text = "Submit").grid(row = 3, column = 0)

After all is done, there's time to position Frames using grid values:

frm_1.grid(row = 0, column = 0)
frm_2.grid(row = 0, column = 1)

Improved Tkinter Frame Script that will print data using Python Shell

First, make sure that you can run it:

from tkinter import *
import tkinter.messagebox as mb
import os

top_win = Tk()
top_win.geometry("800x800")
def sub_nl():
    name = ent_name.get()
    last_name = ent_last_name.get()
    print("Name", name)
    print("LastName", last_name)
    print("-" * 79)

def sub_ap():
    age = ent_age.get()
    pay = ent_pay.get()
    print("Age: ", age)
    print("Pay: ", pay)
    print("-" * 79)

frm_1 = Frame(top_win, highlightbackground = "black", highlightthickness = 1)
frm_2 = Frame(top_win, highlightbackground = "black", highlightthickness = 1)

lab_name = Label(frm_1, text = "Name").grid(row = 0, column = 0)
lab_last_name = Label(frm_1, text = "LastName").grid(row = 1, column = 0)

ent_name = Entry(frm_1)
ent_name.grid(row = 0, column = 1)
ent_last_name = Entry(frm_1)
ent_last_name.grid(row = 1, column = 1)

but_1 = Button(frm_1, text = "Submit", command = sub_nl).grid(row = 3, column = 0)

lab_age = Label(frm_2, text = "Age").grid(row = 0, column = 0)
lab_pay = Label(frm_2, text = "Pay").grid(row = 1, column = 0)

ent_age = Entry(frm_2)
ent_age.grid(row = 0, column = 1)
ent_pay = Entry(frm_2)
ent_pay.grid(row = 1, column = 1)

but_2 = Button(frm_2, text = "Submit", command = sub_ap).grid(row = 3, column = 0)

frm_1.grid(row = 0, column = 0)
frm_2.grid(row = 0, column = 1)

top_win.mainloop()

We will create function that will get data for a name and last name using get() method. After that function will just create simple Python Shell report:

def sub_nl():
    name = ent_name.get()
    last_name = ent_last_name.get()
    print("Name", name)
    print("LastName", last_name)
    print("-" * 79)

Another function will grab and print users age and pay values:

def sub_ap():
    age = ent_age.get()
    pay = ent_pay.get()
    print("Age: ", age)
    print("Pay: ", pay)
    print("-" * 79)

Now we will just upgrade a source for both buttons, connecting it with corresponding functions using "command = " option: 

but_1 = Button(frm_1, text = "Submit", command = sub_nl).grid(row = 3, column = 0)
but_2 = Button(frm_2, text = "Submit", command = sub_ap).grid(row = 3, column = 0)

If you don't understand those scripts give you some time and work with just one button.

There's also corresponding YT tutorial: Tkinter - Frames Explained

Tkinter - Get Value From Entry Fields

In this tutorial we will combine knowledge from previous scripts.

We have only one Label with corresponding Entry field. There is also submit button, but it's not yet connected to real function that will do processing. 

Place where we will see results will be inside dedicated Canvas. This is important to note.

Once we have that arrangement, we can continue with dedicated function that will do something.

So far, this is full working script:

from tkinter import *
import tkinter.messagebox as mb
import os

top_win = Tk()
top_win.geometry("800x800")
        
lab_1 = Label(top_win, text = "Number", bg = "lightyellow")
lab_1.grid(row = 0, column = 0)

ent_1 = Entry(top_win)
ent_1.grid(row = 0, column = 1)

but_1 = Button(top_win, text = "Calculate", bg = "lightgreen")
but_1.grid(row = 1, column = 0)

c = Canvas(top_win, width = 100, heigh = 100, bg = "yellow")
c.grid(row = 2, column = 3)      

top_win.mainloop()

Ok, now it is the time to create function that will get values from entry field with get() method. Once we have data, we can do some simple calculations.

But we also need to have again Canvas to show results there using lab_2 label that deals with text values. This is whole source of function:

def calculate_func():
    number_atm = ent_1.get()
    print_res = (int(number_atm) * 2)

    c = Canvas(top_win, width = 100, heigh = 100, bg = "yellow")
    c.grid(row = 2, column = 3)

    lab_2 = Label(c)
    lab_2["text"] = print_res
    lab_2.grid(row = 1, column = 1)

Once we combine all needed a source, function, label, entry field, Canvases, this is full working script that will process and show results.

And yes, my best advice is to go through dedicated YT tutorial that covers Getting Values from Entry Field in Tkinter.

from tkinter import *
import tkinter.messagebox as mb
import os

top_win = Tk()
top_win.geometry("800x800")

def calculate_func():
    number_atm = ent_1.get()
    print_res = (int(number_atm) * 2)

    c = Canvas(top_win, width = 100, heigh = 100, bg = "yellow")
    c.grid(row = 2, column = 3)

    lab_2 = Label(c)
    lab_2["text"] = print_res
    lab_2.grid(row = 1, column = 1)
        
lab_1 = Label(top_win, text = "Number", bg = "lightyellow")
lab_1.grid(row = 0, column = 0)

ent_1 = Entry(top_win)
ent_1.grid(row = 0, column = 1)

but_1 = Button(top_win, text = "Calculate", bg = "lightgreen", command = calculate_func)
but_1.grid(row = 1, column = 0)

c = Canvas(top_win, width = 100, heigh = 100, bg = "yellow")
c.grid(row = 2, column = 3)      

top_win.mainloop()

Tkinter - Labels and Entry Fields

In this tutorial we will learn how to have Entry fields in Tkitner Canvas. Users need explanations what to type in entry fields so we must create Labels.

First, we will create Canvas with lightgreen background. Position for Canvas is in top_win of size 800 x 800:

can = Canvas(top_win, width = 400, height = 400, bg = "lightgreen")  

 And than, Labels. We will position it using place() method:

user_name = Label(top_win, text = "Username: ")
user_name.place(x = 20, y = 40)

user_pass = Label(top_win, text = "Password: ")
user_pass.place(x = 20, y = 80)

Once we have Labels, it's time to create Entry fields. We also need to place them:

entry_name = Entry(top_win).place(x = 100, y = 40)

entry_pass = Entry(top_win).place(x = 100, y = 80)

After we are done with element positioning, it's time for Canvas using grid values:

can.grid(row = 0, column = 0)

This is full working source:

from tkinter import *
import tkinter.messagebox as mb
import os

top_win = Tk()
top_win.geometry("800x800")

can = Canvas(top_win, width = 400, height = 400, bg = "lightgreen")      

user_name = Label(top_win, text = "Username: ")
user_name.place(x = 20, y = 40)

user_pass = Label(top_win, text = "Password: ")
user_pass.place(x = 20, y = 80)

submit_buton = Button(top_win, text = "Login")
submit_buton.place(x = 20, y = 120)

entry_name = Entry(top_win).place(x = 100, y = 40)

entry_pass = Entry(top_win).place(x = 100, y = 80)

can.grid(row = 0, column = 0)
top_win.mainloop()

Tkinter - Line, Oval, Arc, Rectangle

In last tutorial we mentioned that Canvas will be place where we can have multiple shapes.

First, we will establish Canvas with width of 500 and height of 500, with lightgreen background:

area = Canvas(top_win, width = 500, height = 500, bg = "lightgreen")

Then, we will have an orange rectangle with starting coordinates 10 and 10, with ending coordinates in x = 200 and y = 200:

rec = area.create_rectangle(10, 10, 200, 200, fill = "orange")

Why not have another, yellow rectangle, just for fun:

rec_2 = area.create_rectangle(20, 20, 150, 150, fill = "yellow")

To create an arc we will have something like this:

arc = area.create_arc(30, 30, 300, 300, extent = 223, fill = "red")

What about an oval ? No problem, it's easy:

oval = area.create_oval(10, 10, 300, 50, fill = "yellow")

 It's not enough to have Canvas, we must Grid it. In this case in a cell defined by 0 0 , which means upper top corner:

area.grid(row = 0, column = 0)

Full working source code:  

from tkinter import *
import tkinter.messagebox as mb
import os

top_win = Tk()
top_win.geometry("800x800")

area = Canvas(top_win, width = 500, height = 500, bg = "lightgreen")

rec = area.create_rectangle(10, 10, 200, 200, fill = "orange")
rec_2 = area.create_rectangle(20, 20, 150, 150, fill = "yellow")

arc = area.create_arc(30, 30, 300, 300, extent = 223, fill = "red")

oval = area.create_oval(10, 10, 300, 50, fill = "yellow")
    
area.grid(row = 0, column = 0)
top_win.mainloop()

Ok now we will have a bunch of lines. Their starting and ending coordinates will be randomly generated using random module. Don't forget to import it.

We will use for loop to generate lines:

for x in range(10):
    line = area.create_line(randrange(25, 100), randrange(25, 100),
                            randrange(50, 400), randrange(200, 400))

Full working script:

from tkinter import *
import tkinter.messagebox as mb
import os
from random import *

top_win = Tk()
top_win.geometry("800x800")

area = Canvas(top_win, width = 500, height = 500, bg = "lightgreen")

rec = area.create_rectangle(10, 10, 200, 200, fill = "orange")
rec_2 = area.create_rectangle(20, 20, 150, 150, fill = "yellow")

arc = area.create_arc(30, 30, 300, 300, extent = 223, fill = "red")

oval = area.create_oval(10, 10, 300, 50, fill = "yellow")

for x in range(10):
    line = area.create_line(randrange(25, 100), randrange(25, 100),
                            randrange(50, 400), randrange(200, 400))
    
area.grid(row = 0, column = 0)
top_win.mainloop()

Tkinter - Canvas

Think about Tkinter Canvas as a place where we can have other shapes. That means that we need coordinates and dimensions.

In this case we will have red shape, which will be in primary, top_win, with 800 x 800 dimensions. Width will be 200 and height will be 200. As with other Tkinter elements, it's not enough to have something, we must position it.

In this example, we will use Grids to position elements. Think about Grids as Excel cells. Those cells are determined by intersection of rows and columns:

shape = Canvas(top_win, width = 200, height = 200, bg = "red")
shape.grid(row = 0, column = 0)

Full script with 3 basic shapes, positioned by grid options will be like this:

from tkinter import *
import tkinter.messagebox as mb
import os

top_win = Tk()
top_win.geometry("800x800")

shape = Canvas(top_win, width = 200, height = 200, bg = "red")
shape.grid(row = 0, column = 0)

shape_2 = Canvas(top_win, width = 200, height = 200, bg = "orange")
shape_2.grid(row = 1, column = 1)

shape_3 = Canvas(top_win, width = 200, height = 200, bg = "orangered")
shape_3.grid(row = 2, column = 2)

top_win.mainloop()

Also, we can have Canvases positioned by packing. In that case we need to think about sides and anchoring:

from tkinter import *
import tkinter.messagebox as mb
import os

top_win = Tk()
top_win.geometry("800x800")

shape = Canvas(top_win, width = 200, height = 200, bg = "red")
shape.pack(side = TOP, anchor = NW)

shape_2 = Canvas(top_win, width = 200, height = 200, bg = "orange")
shape_2.pack(side = RIGHT, anchor = NE)

shape_3 = Canvas(top_win, width = 200, height = 200, bg = "orangered")
shape_3.pack(side = BOTTOM, anchor = SW)

top_win.mainloop()

Another option is to experiment with pixels. Placing Canvases py pixels demands in most cases a little bit more time, but at the end of the day we can be happy with precision:

from tkinter import *
import tkinter.messagebox as mb
import os

top_win = Tk()
top_win.geometry("800x800")

shape = Canvas(top_win, width = 200, height = 200, bg = "red")
shape.place(x = 100, y = 100)

shape_2 = Canvas(top_win, width = 200, height = 200, bg = "orange")
shape_2.place(x = 150, y = 150)

shape_3 = Canvas(top_win, width = 200, height = 200, bg = "orangered")
shape_3.place(x = 300, y = 300)

top_win.mainloop()

Monday, April 21, 2025

Tkinter Toplevel - New Window Spawn

Ok, now it's time to pay attention. We will spawn a new window in our Tkinter app by clicking on button.

To do that we will need dedicated function. Just as with a primary window, for spawned window we need to set geometry, which in most cases will be smaller than for a primary app. In this case, 300 x 300.

In that new function we will have independent button that will call some normal function, like to ping Google, or something simple like that.

As with any button, we need to pack it. At the end of net_window() function we will have mainloop:

def net_window():
    net_win = Toplevel()
    net_win.geometry("300x300")

    but_google = Button(net_win, text = "Ping Google", command = ping_google)
    but_google.pack(side = LEFT, anchor = NW)

    net_win.mainloop()

Our normal function (that is doing some useful operation) will just ping Google:

def ping_google():
    os.system("ping google.com")

Now we need to have primary button but_prim that will spawn new app window:

but_prim = Button(top_win, text = "Net Window", command = net_window)
but_prim.pack(side = LEFT, anchor = NW)

You are advised to check corresponding YT tutorial on How to Spawn New Window in Tkinter.

This is full working script:

from tkinter import *
import tkinter.messagebox as mb
import os

top_win = Tk()
top_win.geometry("500x500")

def net_window():
    net_win = Toplevel()
    net_win.geometry("300x300")

    but_google = Button(net_win, text = "Ping Google", command = ping_google)
    but_google.pack(side = LEFT, anchor = NW)

    net_win.mainloop()

def ping_google():
    os.system("ping google.com")

but_prim = Button(top_win, text = "Net Window", command = net_window)
but_prim.pack(side = LEFT, anchor = NW)

top_win.mainloop()

If you don't understand a previous tutorial, give yourself some time. There is no purpose in code memorization, just try to understand an approach. Perhaps code before looks a little bit complicated, bit in fact it is not.

A little bit bigger example

In this example we are improving previous code in such ways that we can have one more button that will spawn new window, and in that window we will have some normal function which will run Notepad. Function to spawn new Notepad window will be this one:

def notepad_window():
    note_window = Toplevel()
    note_window.geometry("300x300")

    but_note = Button(note_window, text = "Notepad", command = run_notepad)
    but_note.pack(side = LEFT, anchor = NW)

    note_window.mainloop()

Function that will run Notepad is this, simple one:

def run_notepad():
    os.system("notepad")

Now, button that will spawn Window where is button to run Notepad is this one:

but_prim_notepad = Button(top_win, text = "Run Notepad", command = notepad_window)
but_prim_notepad.pack(side = LEFT, anchor = NW)

Again as before you are advised to check corresponding YT tutorial on How to Spawn New Window in Tkinter.

This is full working script:

from tkinter import *
import tkinter.messagebox as mb
import os

top_win = Tk()
top_win.geometry("500x500")

def net_window():
    net_win = Toplevel()
    net_win.geometry("300x300")

    but_google = Button(net_win, text = "Ping Google", command = ping_google)
    but_google.pack(side = LEFT, anchor = NW)

    net_win.mainloop()

def notepad_window():
    note_window = Toplevel()
    note_window.geometry("300x300")

    but_note = Button(note_window, text = "Notepad", command = run_notepad)
    but_note.pack(side = LEFT, anchor = NW)

    note_window.mainloop()
    

def ping_google():
    os.system("ping google.com")

def run_notepad():
    os.system("notepad")

but_prim = Button(top_win, text = "Net Window", command = net_window)
but_prim.pack(side = LEFT, anchor = NW)

but_prim_notepad = Button(top_win, text = "Run Notepad", command = notepad_window)
but_prim_notepad.pack(side = LEFT, anchor = NW)

top_win.mainloop()

Tkinter Buttons - Background Image, Relief, Anchor

Tkinter Button Background Image

Yes, we can set real image as background for a button. This time we are using but_2_img that will point to bg-img.gif.

Please note image extension, it must be .gif format:

but_2_img = PhotoImage(file = "bg-img.gif")

 After .gif image is ready and set, we can connect it to button but_2. It's important to have command compound="c":

but_2 = Button(top_win, text="Calc", image = but_2_img, width = 100, height = 100,
               fg = "white", font = ("Arial", 16), compound = "c", command = run_calc)

You are highly advised to watch corresponding YT tutorial that covers this topic.

Other things you know from previous tutorials, so this is our full working script:

from tkinter import *
import tkinter.messagebox as mb
import os

top_win = Tk()
top_win.geometry("500x500")

def run_calc():
    os.system("calc")


but_2_img = PhotoImage(file = "bg-img.gif")
but_2 = Button(top_win, text="Calc", image = but_2_img, width = 100, height = 100,
               fg = "white", font = ("Arial", 16), compound = "c", command = run_calc)
but_2.place(x = 0, y = 0)

top_win.mainloop()

Tkinter Button Packing

If you don't like messing around with pixels for placing buttons somewhere on app windows, we can use pack() method. 

In that case horizontally we can use values LEFT, RIGHT, TOP, BOTTOMDo not use quotes around those uppercase values. 

Also, we will anchor buttons using values like "N", "NE", "E", "SE", "S", "SW", "W", "NW", and also "CENTER". Anchor values are points of the compass:

but_3 = Button(top_win, text="Notepad", command = run_notepad)
but_3.pack(side = LEFT, anchor = NW)

but_4 = Button(top_win, text="Notepad", command = run_notepad)
but_4.pack(side = LEFT, anchor = NW)

Full script: 

from tkinter import *
import tkinter.messagebox as mb
import os

top_win = Tk()
top_win.geometry("500x500")

def run_notepad():
    os.system("notepad")
    
but_3 = Button(top_win, text="Notepad", command = run_notepad)
but_3.pack(side = LEFT, anchor = NW)

but_4 = Button(top_win, text="Notepad", command = run_notepad)
but_4.pack(side = LEFT, anchor = NW)

top_win.mainloop()

Tkinter Button Relief

It's easy to set Relief for buttons. Just use relief uppercase values, without quotes: RAISED, FLAT, SUNKEN, GROOVE or RIDGE:

from tkinter import *
import tkinter.messagebox as mb
import os

top_win = Tk()
top_win.geometry("500x500")

def run_notepad():
    os.system("notepad")
    
but_3 = Button(top_win, text="Notepad", relief = FLAT, command = run_notepad)
but_3.pack(side = LEFT, anchor = NW)

but_4 = Button(top_win, text="Notepad", relief = SUNKEN, command = run_notepad)
but_4.pack(side = LEFT, anchor = NW)

top_win.mainloop()


Tkinter Buttons - Size, Colors, Font

We can play a lot with buttons. Not just with coordinates, but with size, colors and font types:

Interesting thing, to activate all those additional options we need to have blank button with PhotoImage() where width and height must be set:

common_img = PhotoImage(width = 1, height = 1)

For simplicity reasons we will play with one button but_1. There is some things here that must be done.

One of them is set image = common_img.

Width is set to 100 and height to 20.

Background color is defined with bg="lightgreen".

Foreground color is set with fg = "red".

Those colors are static. Once you press button, color can be different.

To set button background while it is pressed we will say activebackground = "white".

An active foreground is set with activeforeground = "orange".

For a font we will use System type, with font = ("System").

Don't forget to connect command= with function run_ping()

Until now our code for a button is this:

common_img = PhotoImage(width = 1, height = 1)

but_1 = Button(top_win, text="Ping Google", image = common_img,
               width = 100, height = 20,
               compound = "c", bg = "lightgreen", fg = "red",
               activebackground = "white", activeforeground = "orange",
               font = ("System"), command = run_ping)

Of course we need button position and mainloop, but we know that from previous tutorials.

This is full working source:

from tkinter import *
import tkinter.messagebox as mb
import os

top_win = Tk()
top_win.geometry("500x500")

def run_ping():
    os.system("ping google.com")

common_img = PhotoImage(width = 1, height = 1)

but_1 = Button(top_win, text="Ping Google", image = common_img,
               width = 100, height = 20,
               compound = "c", bg = "lightgreen", fg = "red",
               activebackground = "white", activeforeground = "orange",
               font = ("System"), command = run_ping)
but_1.place(x = 5, y = 5)

top_win.mainloop()


Tkinter Buttons - Run External Apps from Tkinter

So far soo good. Now we will import os module to have access to system commands:

from tkinter import *
import tkinter.messagebox as mb
import os

 Again we need a main window and geometry:

top_win = Tk()
top_win.geometry("500x500")

Now we are creating 3 independent functions.

First function will ping google.com, or any other domain you like: 

def run_ping():
    os.system("ping google.com")

Second function will run Windows Calculator:

def run_calc():
    os.system("calc")

Third function will run Notepad:

def run_notepad():
    os.system("notepad")

All those functions must have corresponding buttons. Don't forget to set command= to appropriate functions we created. 

Also, for every button we must position it using x and y coordinates. You can experiment with pixel values, those I have in source code works for me:

but_1 = Button(top_win, text = "Ping Google", command = run_ping)
but_1.place(x = 5, y = 5)

but_2 = Button(top_win, text = "Calc", command = run_calc)
but_2.place(x = 82, y = 5)

but_3 = Button(top_win, text = "Notepad", command = run_notepad)
but_3.place(x = 118, y = 5)

Don't forget mainloop at the end of code:

top_win.mainloop()

This is full working script:

from tkinter import *
import tkinter.messagebox as mb
import os

top_win = Tk()
top_win.geometry("500x500")

def run_ping():
    os.system("ping google.com")

def run_calc():
    os.system("calc")

def run_notepad():
    os.system("notepad")
    

but_1 = Button(top_win, text = "Ping Google", command = run_ping)
but_1.place(x = 5, y = 5)

but_2 = Button(top_win, text = "Calc", command = run_calc)
but_2.place(x = 82, y = 5)

but_3 = Button(top_win, text = "Notepad", command = run_notepad)
but_3.place(x = 118, y = 5)

top_win.mainloop()


Python Turtle - Turtle Race - Automatic Winner Detection

This is Turtle Race Game with Automatic Winner Detection.

Run this code and than we will explain how to automatically detect winning turtle:

from turtle import *
import random

t1 = Turtle()
t1.shape("turtle")
t1.speed(0)
t1.penup()
t1.left(90)
t1.color("red")

t2 = t1.clone()
t2.color("yellow")

t1.goto(-300, -300)
t2.goto(300,  -300)
#-----------------------------

finish_1 = Turtle()
finish_1.penup()
finish_1.goto(-300, 300)
finish_1.pendown()
finish_1.circle(20)
finish_1.hideturtle()

finish_2 = Turtle()
finish_2.penup()
finish_2.goto(300, 300)
finish_2.pendown()
finish_2.circle(20)
finish_2.hideturtle()
#-----------------------------

def main():
    for x in range(600):
        t1.fd(random.randrange(10))
        #t1.shapesize(15, 15, 15)
        t2.fd(random.randrange(10))
        #t2.shapesize(15, 15, 15)

        if (t1.position()[1]) >= 300:
            print("Turtle 1 WINS")
            break
        elif (t2.position()[1]) >= 300:
            print("Turtle 2 WINS")
            break        

main()

There's no need to change source for turtle creation and starting points. We will just change custom functions that deals with random movements:

def main():
    for x in range(600):
        t1.fd(random.randrange(10))
        #t1.shapesize(15, 15, 15)
        t2.fd(random.randrange(10))
        #t2.shapesize(15, 15, 15)

        if (t1.position()[1]) >= 300:
            print("Turtle 1 WINS")
            break
        elif (t2.position()[1]) >= 300:
            print("Turtle 2 WINS")
            break        

To speed things up, we are using value 10 as argument for randrange() function.

Then we are introducing if / elif check to detect when any of turtles t1 and t2 reaches position 300 verticaly. How is that done ?

When we say t1.position()[1] >= 300 that means we are checking if t1 is reaching 300 value or more on y (vertical) axis. If that is correct, t1 is winner and there is no need to check more, that's why we need to break.

If t2 reaches 300 or more vertically, same story, t2 is winner and there's break again.

Results will be printed in Python Shell.

This is end of this tutorial, and corresponding YouTube playlist.

Tkinter Introduction - Top Widget, Method, Button

First, let's make shure that our tkinter module is working ok with simple  for loop that will spawn 5 instances of blank Tk window .  ...