Python Forum
[Tkinter] Mouse click without use bind - Printable Version

+- Python Forum (https://python-forum.io)
+-- Forum: Python Coding (https://python-forum.io/forum-7.html)
+--- Forum: GUI (https://python-forum.io/forum-10.html)
+--- Thread: [Tkinter] Mouse click without use bind (/thread-30038.html)



Mouse click without use bind - ATARI_LIVE - Oct-01-2020

I have code with bind which I do not like.
is there another way than bind?
I am looking for counting when the mouse or touchscreen is pressed and hold for about 3 seconds to respond.
Thanks!


RE: Mouse click without use bind - Larz60+ - Oct-01-2020

There is no built-in way to handle Drag and drop, and the only way to do this is to create the functionality yourself.

Quote:is there another way than bind?

The only possible way to do this without bind is to create a low level listener (and this is essentially a home-grown bind), and you don't want to go there unless you thoroughly understand the interrupt process. Bind is a way to capture interrupts within your code, and you need not be afraid of them.

for drag and drop, you need to bind:
  • Button press (In tkinter this looks like <ButtonPress-1> )
  • Button move (In tkinter this looks like <B1-Motion> )
  • Button release (In tkinter this looks like <ButtonRelease-1>
It is not normal, nor needed to time the release, it's captured with the mouse up interrupt.

There are many examples of how to do this. It's quite simple to create your own,
you need create hooks for start, move and, stop activity.

Do a google search for: 'drag and drop for tkinter'

Please not that there is DRag and Drop support comming in ptrhon release 3.9.0 see: https://docs.python.org/3.9/library/tkinter.dnd.html
expected release in just 4 days (Oct 5) or you can download and install the release
see: https://pythoninsider.blogspot.com/2020/09/python-390rc2-is-now-available-for.html?utm_source=feedburner&utm_medium=feed&utm_campaign=Feed%3A+PythonInsider+%28Python+Insider%29

you can find the code for this

if you can't find a suitable example with google,
come back, post your code, and I or another mod/admin will help you write one.

Finally: Perhaps it's time to consider my favorite wxpython, Kivy, or Qt5


RE: Mouse click without use bind - deanhystad - Oct-01-2020

Where is drag and drop mentioned?

If you want to force a 3 second continuous touch before doing some action, you'll need to at least bind to touch and release and use an after to call your eventual callback.
from tkinter import *
after_id = None
root = Tk()

def press_cb(event):
    global after_id
    after_id = root.after(3000, after_cb)

def release_cb(event):
    global after_id
    if after_id is not None:
        root.after_cancel(after_id)
        after_id = None

def after_cb():
    """Do whatever"""
    print('Leg go of me!!')

root.bind('<ButtonPress-1>', press_cb)
root.bind('<ButtonRelease-1>', release_cb)
Or you could combine a few things.
from tkinter import *

root = Tk()

def press_cb(event=None):
    global lp_id
    if event is None:
        print('Let go my Eggo!')
        lp_id = None
    elif event.type == EventType.ButtonPress:
        lp_id = root.after(3000, press_cb)
    elif lp_id:
        root.after_cancel(lp_id)
        lp_id = None

root.bind('<ButtonPress-1>', press_cb)
root.bind('<ButtonRelease-1>', press_cb)
It would be useful to know what you are trying to do, what you have tried to do, and why you are unhappy with what you've done. At least I am confused about what you are asking.


RE: Mouse click without use bind - Larz60+ - Oct-02-2020

Quote:deanhystad asked: Where is drag and drop mentioned?
Somehow, I answered to the wrong thread.
Now I have to find the correct one, and move the post.


RE: Mouse click without use bind - ATARI_LIVE - Oct-02-2020

Thanks for this and I am sorry for I missed to explained, I do not discuss about drag and drop. I talk about like press button and hold that's it.
Like when I press and hold for 3 sec then open the menu.

thanks again!

Let say for example:
if mousepress == 1:
    count = count + 1
else:
    count = 0

if count > 10 and count < 20:
    Print("Still holding")

if count > 50 and count < 60:
    print("That's enough!")

if count > 100:
    Print ("Fine! I am quitting!")
    exit()
The bind do not to continue to pass when press and hold.


RE: Mouse click without use bind - ATARI_LIVE - Oct-06-2020

No one can?


RE: Mouse click without use bind - deanhystad - Oct-06-2020

I provided an example of how you can use bind to execute a delayed event. The mouse does not do hold/repeat like the keyboard, and even if it did, counting is a poor way to measure time.


RE: Mouse click without use bind - joe_momma - Oct-21-2020

here's my attempt:
from tkinter import *

import logging, sys
from time import strftime as s_time, localtime as l_time, time
logging.basicConfig(level= logging.DEBUG)
#logging.disable(logging.CRITICAL)

class Long_Key_Press(Frame):
    def __init__(self, parent=None, HOLD_TIME=10):
        self.parent= parent
        self.HOLD_TIME= HOLD_TIME
        Frame.__init__(self, self.parent)
        self.pack(expand=YES, fill=BOTH)
        
        self.canvas= Canvas(self)
        self.canvas.config(width= 500, height= 700, bg='skyblue')
        self.canvas.pack(expand=YES, fill=BOTH)
        
        self.btn= Button(self.canvas, text='QUIT', command= self.get_entry)
        self.btn.place(x=400,y=600)
        
        self.time_txt= StringVar()
        self.lbl_1= Label(self.canvas, textvariable= self.time_txt,
                          font=('arial',25,'bold'))
        self.lbl_1.place(x=20,y=50)

        self.output_lbl= StringVar()
        self.lbl_2= Label(self.canvas, textvariable= self.output_lbl,
                          font=('arial',25,'bold'))
        self.lbl_2.place(x=20,y=200)
        self.output_lbl.set('Hold left mouse down')
        
        self.bind_all('<Key>', self.key)
        self.canvas.bind('<Button-1>', self.left_mouse_down)
        self.canvas.bind('<ButtonRelease-1>', self.left_mouse_up)

        self.time_elapsed= 0.0
        
        self.counter= 0
        self.g_count=0
    def set_timer(self,elapsed):
        self.minutes= int(elapsed/60)
        self.seconds= int(elapsed- self.minutes*60.0)
        self.hseconds= int((elapsed- self.minutes*60.0 - self.seconds)*100)
        self.time_txt.set('%02d:%02d:%02d'%(self.minutes,
                                            self.seconds,
                                            self.hseconds))
    def update_time(self):
        self.time_elapsed= time() - self.start
        self.set_timer(self.time_elapsed)
        if self.seconds == self.HOLD_TIME * .25:
            self.output_lbl.set('Quarter way there...')
        elif self.seconds == self.HOLD_TIME * .5:
            self.output_lbl.set('Half way there...')
        elif self.seconds == self.HOLD_TIME * .75:
            self.output_lbl.set("3/4 the to finish...")
        elif self.seconds >= self.HOLD_TIME:
            self.output_lbl.set('One second longer....')
        
        self._timer= self.after(50, self.update_time)
    def left_mouse_down(self, event):
        x,y= event.x, event.y
        self.start= time() - self.time_elapsed
        self.update_time()
        
    def left_mouse_up(self, event):
        self.after_cancel(self._timer)
        self.time_elapsed= 0.0
        
        if self.seconds > self.HOLD_TIME:
            self.output_lbl.set("That is long enough.")
            self.canvas.config(bg='lime')
        else:
            self.output_lbl.set("Longer hold is required.")
            self.canvas.config(bg='red')
        
        
    def key(self, event):
        self.g_count +=1
        message= 'count:{0} key:{1} num:{2} state:{3}'.format(self.g_count,
                                                 event.keysym,event.keysym_num,
                                       event.state)
        logging.debug(message)
        
    def get_entry(self):
        self.parent.destroy()
if __name__ == '__main__':
    root= Tk()
    Long_Key_Press(root, HOLD_TIME=20)
    root.mainloop()



RE: Mouse click without use bind - ATARI_LIVE - Oct-23-2020

(Oct-21-2020, 03:08 PM)joe_momma Wrote: here's my attempt:
from tkinter import *

import logging, sys
from time import strftime as s_time, localtime as l_time, time
logging.basicConfig(level= logging.DEBUG)
#logging.disable(logging.CRITICAL)

class Long_Key_Press(Frame):
    def __init__(self, parent=None, HOLD_TIME=10):
        self.parent= parent
        self.HOLD_TIME= HOLD_TIME
        Frame.__init__(self, self.parent)
        self.pack(expand=YES, fill=BOTH)
        
        self.canvas= Canvas(self)
        self.canvas.config(width= 500, height= 700, bg='skyblue')
        self.canvas.pack(expand=YES, fill=BOTH)
        
        self.btn= Button(self.canvas, text='QUIT', command= self.get_entry)
        self.btn.place(x=400,y=600)
        
        self.time_txt= StringVar()
        self.lbl_1= Label(self.canvas, textvariable= self.time_txt,
                          font=('arial',25,'bold'))
        self.lbl_1.place(x=20,y=50)

        self.output_lbl= StringVar()
        self.lbl_2= Label(self.canvas, textvariable= self.output_lbl,
                          font=('arial',25,'bold'))
        self.lbl_2.place(x=20,y=200)
        self.output_lbl.set('Hold left mouse down')
        
        self.bind_all('<Key>', self.key)
        self.canvas.bind('<Button-1>', self.left_mouse_down)
        self.canvas.bind('<ButtonRelease-1>', self.left_mouse_up)

        self.time_elapsed= 0.0
        
        self.counter= 0
        self.g_count=0
    def set_timer(self,elapsed):
        self.minutes= int(elapsed/60)
        self.seconds= int(elapsed- self.minutes*60.0)
        self.hseconds= int((elapsed- self.minutes*60.0 - self.seconds)*100)
        self.time_txt.set('%02d:%02d:%02d'%(self.minutes,
                                            self.seconds,
                                            self.hseconds))
    def update_time(self):
        self.time_elapsed= time() - self.start
        self.set_timer(self.time_elapsed)
        if self.seconds == self.HOLD_TIME * .25:
            self.output_lbl.set('Quarter way there...')
        elif self.seconds == self.HOLD_TIME * .5:
            self.output_lbl.set('Half way there...')
        elif self.seconds == self.HOLD_TIME * .75:
            self.output_lbl.set("3/4 the to finish...")
        elif self.seconds >= self.HOLD_TIME:
            self.output_lbl.set('One second longer....')
        
        self._timer= self.after(50, self.update_time)
    def left_mouse_down(self, event):
        x,y= event.x, event.y
        self.start= time() - self.time_elapsed
        self.update_time()
        
    def left_mouse_up(self, event):
        self.after_cancel(self._timer)
        self.time_elapsed= 0.0
        
        if self.seconds > self.HOLD_TIME:
            self.output_lbl.set("That is long enough.")
            self.canvas.config(bg='lime')
        else:
            self.output_lbl.set("Longer hold is required.")
            self.canvas.config(bg='red')
        
        
    def key(self, event):
        self.g_count +=1
        message= 'count:{0} key:{1} num:{2} state:{3}'.format(self.g_count,
                                                 event.keysym,event.keysym_num,
                                       event.state)
        logging.debug(message)
        
    def get_entry(self):
        self.parent.destroy()
if __name__ == '__main__':
    root= Tk()
    Long_Key_Press(root, HOLD_TIME=20)
    root.mainloop()

That's works but almost!... not for me. I really thankful for this.