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
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.
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
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:
See also
- python
- Tcl/Tk
- PySimpleGUI
- Python:Tkinter
- TkinterWeb
- async-tkinter-loop
- Tkinter-Designer (Tkinter, Python, Figma)
Favorite site
- tkinter — Python interface to Tcl/Tk
- Python Tkinter GUI programming
- Python tkinter tutorial : Lesson 1 - Creating a GUI - YUN DAE HEE