Skip to content
Search

Python:tkinter

lastmod 2024-09-07created 2021-06-1320 edits

The tkinter package ("Tk interface") is the standard Python interface to the Tk GUI toolkit. Both Tk and tkinter are available on most Unix platforms, as well as on Windows systems. (Tk itself is not part of Python; it is maintained at ActiveState.)

Running <codee>python -m tkinter</code> from the command line should open a window demonstrating a simple Tk interface, letting you know that tkinter is properly installed on your system, and also showing what version of Tcl/Tk is installed, so you can read the Tcl/Tk documentation specific to that version.

Widgets

  • Button - A simple button
  • Label - Displays text or an image
  • CheckButton - Checkbox
  • Entry - A simple single-line text box
  • ListBox - List box
  • RadioButton - Option button
  • Message - Displays text like Label. Unlike Label, it has automatic wrapping.
  • Scale - Slice bar
  • Scrollbar - Scroll bar
  • Text - A multi-line text box that provides some Rich Text features
  • Menu - Menu pane
  • Menubutton - Menu button
  • Toplevel - Used to create a new window. Tk() creates a window automatically, but use Toplevel when creating additional new windows or dialogs
  • Frame - Container widget. Used to group other widgets
  • Canvas - Can draw pictures with graphs and points, and can also be used to make custom widgets

Open File Dialog

from tkinter import filedialog as fd
filename = fd.askopenfilename()

Python:tkinter with OpenCV

How to draw OpenCV onto Python:Tkinter. See OpenCV:Example:Tkinter.

Making components resize to fit the window size

Pay attention to the arguments when using the pack function.

self.c=Canvas(…)
self.c.pack(fill="both", expand=True)

Event Object

An event handler (event callback) takes a single parameter called event, which is a Tkinter Event Object with the following attributes. In example #2 above, you can see that the click() function receives the event parameter and uses this event's x, y coordinates.

  • char - A single character produced by a keyboard event
  • keysym - The symbol name of the key produced by a keyboard event
  • num - The button number of a mouse event. 1, 2, 3 from the left
  • x, y - Mouse position relative to the top-left of the widget
  • x_root, y_root - Mouse position relative to the top-left of the screen
  • Key - The widget where the event occurred

Asyncio with tkinter

import tkinter as tk
from tkinter import ttk
import asyncio


class App:
    async def exec(self):
        self.window = Window(asyncio.get_event_loop())
        await self.window.show();


class Window(tk.Tk):
    def __init__(self, loop):
        self.loop = loop
        self.root = tk.Tk()
        self.animation = "░▒▒▒▒▒"
        self.label = tk.Label(text="")
        self.label.grid(row=0, columnspan=2, padx=(8, 8), pady=(16, 0))
        self.progressbar = ttk.Progressbar(length=280)
        self.progressbar.grid(row=1, columnspan=2, padx=(8, 8), pady=(16, 0))
        button_block = tk.Button(text="Calculate Sync", width=10, command=self.calculate_sync)
        button_block.grid(row=2, column=0, sticky=tk.W, padx=8, pady=8)
        button_non_block = tk.Button(text="Calculate Async", width=10, command=lambda: self.loop.create_task(self.calculate_async()))
        button_non_block.grid(row=2, column=1, sticky=tk.W, padx=8, pady=8)

    async def show(self):
        while True:
            self.label["text"] = self.animation
            self.animation = self.animation[1:] + self.animation[0]
            self.root.update()
            await asyncio.sleep(.1)

    def calculate_sync(self):
        max = 3000000
        for i in range(1, max):
            self.progressbar["value"] = i / max * 100

    async def calculate_async(self):
        max = 3000000
        for i in range(1, max):
            self.progressbar["value"] = i / max * 100
            if i % 1000 == 0:
                await asyncio.sleep(0)

asyncio.run(App().exec())

Another version

# This demo is a transliteration of the below referenced demo to use the async/await syntax
#
#https://www.reddit.com/r/Python/comments/33ecpl/neat_discovery_how_to_combine_asyncio_and_tkinter/

#
# For testing purposes you may use the following command to create a test daemon:
# tail -f /var/log/messages | nc -l 5900
# Enter localhost:5900 in the entry box to connect to it.

from tkinter import *
import asyncio

async def run_tk(root, interval=0.05):
    '''
    Run a tkinter app in an asyncio event loop.
    '''
    try:
        while True:
            root.update()
            await asyncio.sleep(interval)
    except TclError as e:
        if "application has been destroyed" not in e.args[0]:
            raise

async def tclient(addr,port):
    print('tclient',addr,port)
    try:
        sock ,_= await asyncio.open_connection(host=addr,port=port)
       #print(sock)
       #f=sock.as_stream()
        while True:
               #data = yield from f.readline() 
                data = await sock.readline()
                if not data:break
                data=data.decode()
                print(data,end='\n' if data[-1]=='\r' else'')
    except:
        pass


async def main():
    root = Tk()
    entry = Entry(root)
    entry.grid()

    def spawn_ws_listener():
       addr=entry.get().split(':')
       print('spawn',addr)
       return asyncio.ensure_future( tclient( addr[0],int(addr[1]) ) )

    Button(root, text='Connect', command=spawn_ws_listener).grid()

    await run_tk(root)

if __name__ == "__main__":
    asyncio.get_event_loop().run_until_complete(main())

Troubleshooting

AttributeError: 'PhotoImage' object has no attribute '_PhotoImage__photo'

The following error occurs

AttributeError: 'PhotoImage' object has no attribute '_PhotoImage__photo'

The corresponding code:

from PIL.ImageTk import PhotoImage
from numpy import uint8, zeros

empty = zeros((height, width, 3), dtype=uint8)
photo = PhotoImage(empty)

Fix it as follows:

from PIL.Image import fromarray

photo = PhotoImage(image=fromarray(empty))

See also

Favorite site

author Zer0 sitemap