You can create bindings for the <ButtonPress> and <ButtonRelease> events independently.

A good starting point for learning about events and bindings is here: http://effbot.org/tkinterbook/tkinter-events-and-bindings.htm

Here's a working example:

import Tkinter as tk
import time

class Example(tk.Frame):
    def __init__(self, *args, **kwargs):
        tk.Frame.__init__(self, *args, **kwargs)
        self.button = tk.Button(self, text="Press me!")
        self.text = tk.Text(self, width=40, height=6)
        self.vsb = tk.Scrollbar(self, command=self.text.yview)
        self.text.configure(yscrollcommand=self.vsb.set)

        self.button.pack(side="top")
        self.vsb.pack(side="right", fill="y")
        self.text.pack(side="bottom", fill="x")

        self.button.bind("<ButtonPress>", self.on_press)
        self.button.bind("<ButtonRelease>", self.on_release)

    def on_press(self, event):
        self.log("button was pressed")

    def on_release(self, event):
        self.log("button was released")

    def log(self, message):
        now = time.strftime("%I:%M:%S", time.localtime())
        self.text.insert("end", now + " " + message.strip() + "\n")
        self.text.see("end")

if __name__ == "__main__":
    root = tk.Tk()
    Example(root).pack(side="top", fill="both", expand=True)
    root.mainloop()
Answer from Bryan Oakley on Stack Overflow
๐ŸŒ
Python Course
python-course.eu โ€บ tkinter โ€บ events-and-binds-in-tkinter.php
16. Events and Binds in Tkinter | Tkinter | python-course.eu
#!/usr/bin/python3 # write tkinter as Tkinter to be Python 2.x compatible from tkinter import * def hello(event): print("Single Click, Button-l") def quit(event): print("Double Click, so let's stop") import sys; sys.exit() widget = Button(None, text='Mouse Clicks') widget.pack() widget.bind('<Button-1>', hello) widget.bind('<Double-1>', quit) widget.mainloop()
Discussions

python - Tkinter interpreting the long press of the button as many press and release events - Stack Overflow
A simplistic approach would be ... and reset when it's released. You can set the flag as soon as the button press event is detected, and use it to ignore subsequent firings of the event caused by key repeats while Up is being held. import tkinter as tk def up(): if not ... More on stackoverflow.com
๐ŸŒ stackoverflow.com
Python Tkinter Button Release event movement with pressed button problem - Stack Overflow
I'm trying to make simple block game with tkinter, but I've noticed a problem with ButtonRelease event - for example I have two rectangles connected to same function with different parameters. When I press the first one, move the mouse to the second one and release button over it, it runs the ... More on stackoverflow.com
๐ŸŒ stackoverflow.com
python - Tkinter KeyPress and KeyRelease events - Stack Overflow
When key is released - it is a ... that the button will not be pressed in the nearest time. We don't know the future at the time of releasing the key, so we need to create timer that will call checker function which will verify, that there was not ant repeated pressed in small time interval, is if so - we confirm the release event. from tkinter import * import ... More on stackoverflow.com
๐ŸŒ stackoverflow.com
Tkinter: distinguish between double-click & button release?
Drop the buttonrelease bind and use trace to bind those WhateverVars directly to slider changed. More on reddit.com
๐ŸŒ r/learnpython
5
4
August 21, 2024
๐ŸŒ
TutorialsPoint
tutorialspoint.com โ€บ how-can-i-identify-when-a-button-is-released-in-tkinter
How can I identify when a Button is released in Tkinter?
This can be achieved by passing the <Button Release> parameter in the bind(<ButtonRelease>, callback) method. # Import the required libraries from tkinter import * # Create an instance of tkinter frame or window win=Tk() # Set the size of the window win.geometry("700x350") # Define a function ...
๐ŸŒ
Raspberry Pi Forums
forums.raspberrypi.com โ€บ board index โ€บ programming โ€บ python
Python Tkinter GUI button hold down - Raspberry Pi Forums
import Tkinter as tk class MyBtn(tk.Button): # set function to call when pressed def set_down(self,fn): self.bind('<Button-1>',fn) # set function to be called when released def set_up(self,fn): self.bind('<ButtonRelease-1>',fn) class Mainframe(tk.Frame): def __init__(self,master,*args,**kwargs): tk.Frame.__init__(self,master,*args,**kwargs) # create the button and set callback functions btn = MyBtn(self,text = 'Press ') btn.set_up(self.on_up) btn.set_down(self.on_down) btn.pack() # function called when pressed def on_down(self,x): print("Button down") # function called when released def on_up(self,x): print("Button up") class App(tk.Tk): def __init__(self): tk.Tk.__init__(self) self.title('My Button') self.geometry('250x50') Mainframe(self).pack() # create and run an App object App().mainloop() This program prints a message when the button is pressed or released.
๐ŸŒ
Tutorialspoint
tutorialspoint.com โ€บ python โ€บ tk_button.htm
Tkinter Button
You can attach a function or a method to a button which is called automatically when you click the button. Here is the simple syntax to create this widget โˆ’ ... options โˆ’ Here is the list of most commonly used options for this widget. These options can be used as key-value pairs separated by commas. Following are commonly used methods for this widget โˆ’ ... from tkinter import * from tkinter import messagebox top = Tk() top.geometry("100x100") def helloCallBack(): msg=messagebox.showinfo( "Hello Python", "Hello World") B = Button(top, text ="Hello", command = helloCallBack) B.place(x=50,y=50) top.mainloop()
๐ŸŒ
Python Forum
python-forum.io โ€บ thread-15631.html
Tkinter Button Settings
I have a problem about buttons. Example: root=Tk() def callback(): print('My name is Kaan') buton=ttk.Button(root, text='Callback', command=callback) buton.pack()That's okay. It works but it works when I pulled click from button. I need my fu...
๐ŸŒ
Python
bugs.python.org โ€บ issue31483
Issue 31483: ButtonPress event not firing until button release Python 3.6.1 - Python tracker
This issue tracker has been migrated to GitHub, and is currently read-only. For more information, see the GitHub FAQs in the Python's Developer Guide ยท This issue has been migrated to GitHub: https://github.com/python/cpython/issues/75664
Find elsewhere
๐ŸŒ
Stack Overflow
stackoverflow.com โ€บ questions โ€บ 78765384 โ€บ tkinter-interpreting-the-long-press-of-the-button-as-many-press-and-release-even
python - Tkinter interpreting the long press of the button as many press and release events - Stack Overflow
A simplistic approach would be to use a variable to store a Boolean flag that gets set when Up is pressed, and reset when it's released. You can set the flag as soon as the button press event is detected, and use it to ignore subsequent firings ...
๐ŸŒ
Plus2Net
plus2net.com โ€บ python โ€บ tkinter-events-typing.php
Typing keys to simulate key press and release effects using events in Tkinter
February 5, 2019 - def my_release(event): for widget in my_w.winfo_children(): # all widget classes of the application if isinstance(widget, tk.Button): # if belongs to button class widget['relief']='raised' # Update the relief option to raised Full code is here ยท import tkinter as tk # Python 3 my_w = tk.Tk() my_w.geometry("475x200") def my_callback(event): # When any key is pressed l1.config(text=event.char) # Update the text on Label for widget in my_w.winfo_children(): # Collect all classes of the widgets if isinstance(widget, tk.Button): # If it belongs to button class if widget['text']==event.char or widg
๐ŸŒ
Raspberry Pi Forums
forums.raspberrypi.com โ€บ board index โ€บ programming โ€บ python
Push button function with tkinter - Raspberry Pi Forums
As well did as per the manual install all drivers and did calibration. Then I changed the code to 3 big buttons, so inaccuracy should not be the issue anymore. Now when I press, there is not action, but a small blinking when I release. One more video: https://onedrive.live.com/download?cid= ... JxQzHU0DhQ Code: https://onedrive.live.com/download?cid= ... hXV2PmzCtg Thanks again, N ... import tkinter as tk import time class Example(tk.Frame): def __init__(self, *args, **kwargs): tk.Frame.__init__(self, *args, **kwargs) self.button = tk.Button(self, text="Press me!") self.text = tk.Text(self, wi
๐ŸŒ
Python Tutorial
pythontutorial.net โ€บ home โ€บ tkinter tutorial โ€บ tkinter button
Tkinter Button - Python Tutorial
April 3, 2025 - In this tutorial, you'll learn about the Tkinter Button widget and how to use it to create various kinds of buttons.
๐ŸŒ
Stack Overflow
stackoverflow.com โ€บ questions โ€บ 76515892 โ€บ python-tkinter-button-release-event-movement-with-pressed-button-problem
Python Tkinter Button Release event movement with pressed button problem - Stack Overflow
A button release event will always be reported on the widget or canvas item that received the press event. Instead, you can bind once to the canvas as a whole and use the x/y coordinate of the event to compute the i,j values in the same way ...
Top answer
1 of 9
23

Ok some more research found this helpful post which shows this is occuring because of X's autorepeat behaviour. You can disable this by using

os.system('xset r off')

and then reset it using "on" at the end of your script. The problem is this is global behaviour - not just my script - which isn't great so I'm hoping someone can come up with a better way.

2 of 9
7

Well, this is a bit late now, but I have a solution that works. It's not great, but it does not require os.system overwriting system settings, which is nice.

Basically, I make a class that records the timing of key presses. I say that a key is down when it has been pressed in the last short amount of time (here, .1ms). To get a press, it is easy enough: if the key is not registered as pressed, trigger the event. For releases, the logic is harder: if there is a suspected release event, set a timer for a short time (here, .1s) and then check to make sure the key is not down.

Once you have validated a press or release, call the on_key_press or on_key_release methods in your code. As for those, just implement them the way you originally wanted them

I know this is not perfect, but I hope it helps!!

Here is the code:

Where you are initializing keypress events:

key_tracker = KeyTracker()
window.bind_all('<KeyPress>', key_tracker.report_key_press)
window.bind_all('<KeyRelease>', key_tracker.report_key_release)
key_tracker.track('space')

Here is my custom KeyTracker class:

class KeyTracker():
    key = ''
    last_press_time = 0
    last_release_time = 0

    def track(self, key):
        self.key = key

    def is_pressed(self):
        return time.time() - self.last_press_time < .1

    def report_key_press(self, event):
        if event.keysym == self.key:
            if not self.is_pressed():
                on_key_press(event)
            self.last_press_time = time.time()

    def report_key_release(self, event):
        if event.keysym == self.key:
            timer = threading.Timer(.1, self.report_key_release_callback, args=[event])
            timer.start()

    def report_key_release_callback(self, event):
        if not self.is_pressed():
            on_key_release(event)
        self.last_release_time = time.time()
๐ŸŒ
TutorialsPoint
tutorialspoint.com โ€บ tkinter-keypress-keyrelease-events
TkInter keypress, keyrelease events
June 7, 2021 - Here's how to create a simple application that responds to key press and release events ? # Import the required libraries from tkinter import * # Create an instance of tkinter frame or window win = Tk() # Set the size of the window win.geometry("700x350") win.title("Key Press/Release Events") # Define functions to handle key events def key_press(event): label.config(text="Welcome to TutorialsPoint", fg="blue") def key_released(event): label.config(text="Press any Key...", fg="black") # Create a label widget to display messages label = Label(win, text="Press any Key...", font=('Helvetica', 17, 'bold')) label.pack(pady=50) # Bind the key events to the window win.bind('<KeyPress>', key_press) win.bind('<KeyRelease>', key_released) # Make sure the window can receive focus win.focus_set() win.mainloop()
๐ŸŒ
Reddit
reddit.com โ€บ r/learnpython โ€บ tkinter: distinguish between double-click & button release?
r/learnpython on Reddit: Tkinter: distinguish between double-click & button release?
August 21, 2024 -

Hello,

So I have a (relatively) slow callback function which needs to be called only when the UI has absolutely settled on a set of values, while still being a fairly reactive UI (meaning, I'd rather not have an "Apply" button).... The function runs fast enough, as long as it's not called several times in a row.

I would like to be able to run the callback whenever the following happens:

  1. A slider (aka Scale widget) has changed and stopped moving

  2. Double-clicking on the slider to reset to a default value

Of course, I got double-click working, by binding <Double-Button-1> (which actually runs a separate callback, to look up the default value & adjust the widget, before running the normal callback).

Then, without thinking much, I tried binding <ButtonRelease-1> to handle any other change.

This naturally results in double-clicks triggering two button releases, and thus, 2 extra calls to my callback.

My own digging lead to trying the `.trace` method on my Tk Variables, but that just made it far worse, since it tracks changes in real time.

So with that, the only question I know how to ask with my current knowledge of Tkinter & UI design in general, is in the title. However, more accurately, in what way am I approaching this problem wrong?

Thanks for reading!!

p.s. Here's a first effort of boiling down some of my code (it obviously will not run on its own, but should convey every part of my current approach/problem...and Note: I'm using a modular toolbar, so it adds to the complexity of reading it a bit...sorry):

def slider_changed(*args, **kwargs):
    """Called on button release; duplicated by double-click, but should only run when
       UI has settled.
    """
    update_img(**get_params())


def slider_reset(event):
    """Called on double click...Resets slider to default, then runs slider_changed()
    """
    defval = toolbar_def[event.widget.cget("label")][3]

    # Not sure why I did this, instead of just calling them directly
    tkroot.after(1, lambda: event.widget.set(defval))
    tkroot.after(10, lambda: slider_changed(event))


toolbar = tk.Frame(tkroot, background = root_bg)
toolbar.pack()

toolbar_def = {
#   Label         :  0min    , 1max   , 2res , 3def, 4param       , 5type
    "Offset X"    : (-imgsize, imgsize, 1    , 0   , "offsx"      , tk.IntVar    ),
    "Offset Y"    : (-imgsize, imgsize, 1    , 0   , "offsy"      , tk.IntVar    ),
    "Scale X"     : (-1      ,   1    , 0.001, 0.01, "sclx"       , tk.DoubleVar ),
    "Scale Y"     : (-1      ,   1    , 0.001, 0.01, "scly"       , tk.DoubleVar ),
    "Octaves"     : ( 1      ,  10    , 1    , 4   , "octaves"    , tk.IntVar    ),
    "Persistence" : (-0.99   ,   1    , 0.01 , 0.5 , "persistence", tk.DoubleVar ),
    "Lacunarity"  : (-10     ,  10    , 0.1  , 2   , "lacunarity" , tk.DoubleVar ),
    "Threshold"   : (  0     , 255    , 1    , 128 , "threshold"  , tk.IntVar    ),
    "Seed"        : (-262144 , 262144 , 1    , 0   , "seed"       , tk.IntVar    ),
    "Tile"        : (0       ,      1 , 1    , 1   , "tile"       , tk.BooleanVar)
}

for label, data in toolbar_def.items():
    frame = tk.Frame(toolbar)

    tkvar = data[5](value = data[3])
    # Tried using tkvar.trace() here but it tracks every change close to real time, 
    # which is much worse

    slider = tk.Scale(
        frame,
        label = label,
        from_ = data[0],
        to = data[1],
        resolution = data[2],
        orient = "horizontal",
        length = 512,
        variable = tkvar
    )

    slider.bind("<Double-Button-1>", slider_reset) # No good - triggers 2 releases
    slider.bind("<ButtonRelease-1>", slider_changed)

    slider.pack(side = "left", ipady = 21)

    frame.pack()
๐ŸŒ
w3resource
w3resource.com โ€บ python-exercises โ€บ tkinter โ€บ python-tkinter-basic-exercise-7.php
Python Tkinter event handling: Button clicks
August 19, 2025 - import tkinter as tk # Create the main window root = tk.Tk() root.title("Button Click Event Handling") # Create a label widget label = tk.Label(root, text="Click the button and check the message text:") label.pack() # Function to handle button click event def on_button_click(): label.config(text="Button Clicked!") # Create a button widget button = tk.Button(root, text="Click Me", command=on_button_click) button.pack() # Start the Tkinter event loop root.mainloop()
๐ŸŒ
Dafarry
dafarry.github.io โ€บ tkinterbook โ€บ tkinter-events-and-bindings.htm
Events and Bindings
When you press down a mouse button over a widget, Tkinter will automatically โ€œgrabโ€ the mouse pointer, and subsequent mouse events (e.g. Motion and Release events) will then be sent to the current widget as long as the mouse button is held down, even if the mouse is moved outside the current ...