I have multiple buttons in tkinter window, but on a computer we only have one mouse pointer at one location at a time, how can I multi-press buttons simultaneously just like on a touch screen?
Here is a sample code of what I am trying to do,
#!/usr/bin/python
import Tkinter as Tk
def button_pressed_cb(event):
print("You pressed " + event.widget['text'])
def button_release_cb(event):
print("You released " + event.widget['text'])
root = Tk.Tk()
button1 = Tk.Button(root, text="button1")
button1.pack()
button2 = Tk.Button(root, text="button2")
button2.pack()
button1.bind("<ButtonPress>", button_pressed_cb)
button1.bind("<ButtonRelease>", button_release_cb)
button2.bind("<ButtonPress>", button_pressed_cb)
button2.bind("<ButtonRelease>", button_release_cb)
root.mainloop()
After executing this, I get a sample output of something like this,
You pressed button1
You released button1
You pressed button2
You released button2
What I want to achieve is to be able to generate events which occur in this sequence,
You pressed button1
You pressed button2
You released button2
You released button1
Does anybody know what's the best way to achieve this? Thank you so much.
If you just want to call the callbacks, you can do that—they're ordinary Python functions, after all.
If you're asking how to create an event and dispatch it, you can use the event_generate
method. Unfortunately, I don't know of any tkinter documentation for this, so you have to look at the Tcl/Tk docs instead. But the basic idea is:
def hit_the_buttons():
button1.event_generate('<ButtonPress>', when='tail')
button2.event_generate('<ButtonPress>', when='tail')
button2.event_generate('<ButtonRelease>', when='tail')
button1.event_generate('<ButtonRelease>', when='tail')
The when
argument puts the events at the end of the event queue rather than processing them immediately, so they won't interfere with things like redraws or actual mouse events. It isn't really necessary here; I included it mainly to show how to map one of those Tcl arguments ( -when tail
) to tkinter.
If you want this to go through the normal dispatch instead of directly to the buttons, you can call root.event_generate
and pass x
and y
arguments that will hit-test as inside the buttons.
Ok, I found a solution. I put in extra checks that if user presses and holds ctrl before clicking a button, that button will latch on to that pressed state. Then user can go and click other button etc. User can click that button again to unlatch it.
I also added a hover message as well for user to tell the user they can use ctrl to latch a button and achieve multikey presses.
Here is the new code,
#!/usr/bin/python
import Tkinter as Tk
class HoverInfo(Tk.Menu):
def __init__(self, parent, text):
Tk.Menu.__init__(self, parent, tearoff=0,
background='light goldenrod yellow')
self.__displayed = False
for line in text.split('\n'):
self.add_command(label=line)
parent.bind("<Enter>", self.__display)
parent.bind("<Leave>", self.__remove)
def __display(self, event):
if event.widget['state'] == Tk.NORMAL:
if not self.__displayed:
self.__displayed = True
self.post(event.x_root+5, event.y_root+5)
def __remove(self, event):
if self.__displayed:
self.__displayed = False
self.unpost()
CONTROL = 4
def button_pressed_cb(event):
if event.widget['state'] != Tk.DISABLED:
print("You pressed " + event.widget['text'])
if (event.state & CONTROL) == CONTROL:
event.widget.config(state=Tk.DISABLED)
event.widget.config(relief=Tk.SUNKEN)
def button_release_cb(event):
if (event.state & CONTROL) != CONTROL:
print("You released " + event.widget['text'])
event.widget.config(state=Tk.NORMAL)
event.widget.config(relief=Tk.RAISED)
root = Tk.Tk()
button1 = Tk.Button(root, text="button1")
button1.pack()
button2 = Tk.Button(root, text="button2")
button2.pack()
button1.bind("<ButtonPress>", button_pressed_cb)
button1.bind("<ButtonRelease>", button_release_cb)
button2.bind("<ButtonPress>", button_pressed_cb)
button2.bind("<ButtonRelease>", button_release_cb)
HoverInfo(button1, "Hint:\nYou can hold Ctrl key before\nclicking a button to latch it.")
root.mainloop()
Now, this is how the hover message looks, https://ibb.co/dEb6Bn
And when user holds ctrl key and clicks button 1 and then button 2, then this is how it looks, https://ibb.co/eVzRBn
Now, I can easily generate this sequence of events,
You pressed button1
You pressed button2
You released button2
You released button1
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.