tkinter button not doing anything - python

How come this isn't working? When I press the YES button that works, but when I press the NO button nothing happens.
def yespress(event):
print("Yes PRESSED")
def nopress(event):
print("No PRESSED")
## TKINTER SETUP
win = Tk()
win.title("Selector")
win.geometry('220x50')
Button_Yes = ttk.Button(win, text="YES")
Button_No = ttk.Button(win, text="NO")
Button_Yes.bind('<Button-1>', yespress)
Button_Yes.pack()
Button_No.bind('<Button-2>', nopress)
Button_No.pack()```

The problem is Not with the code you are a liitlbe bit confused with the
widget.bind(event,handler)
method.
this method handle the events that occur on the widget.
in your case you are handling the single click event here
Button_Yes.bind('<Button-1>', yespress)
but what about this method
Button_No.bind('<Button-2>', nopress)
what you really want to acheive because there is no event with name
"Button-2"
the "Button-1" event is for single click event. but if you want to listen to a
double click you should use
"Double-2" not "Button-2".
I hope i answer your question.
Feel free to ask.
for more about the bind method please read this.
https://www.python-course.eu/tkinter_events_binds.php

Related

How to detect which key was pressed on keyboard/mouse using tkinter/python?

I'm using tkinter to make a python app and I need to let the user choose which key they will use to do some specific action. Then I want to make a button which when the user clicks it, the next key they press as well in keyboard as in mouse will be detected and then it will be bound it to that specific action. How can I get the key pressed by the user?
To expand on #darthmorf's answer in order to also detect mouse button events, you'll need to add a separate event binding for mouse buttons with either the '<Button>' event which will fire on any mouse button press, or '<Button-1>', (or 2 or 3) which will fire when that specific button is pressed (where '1' is the left mouse button, '2' is the right, and '3' is the middle...though I think on Mac the right and middle buttons are swapped).
import tkinter as tk
root = tk.Tk()
def on_event(event):
text = event.char if event.num == '??' else event.num
label = tk.Label(root, text=text)
label.place(x=50, y=50)
root.bind('<Key>', on_event)
root.bind('<Button>', on_event)
root.mainloop()
You can get key presses pretty easily. Without knowing your code, it's hard to say exactly what you will need, but the below code will display a label with the last key pressed when ran and should provide enough of an example to show you how to adapt it to your program!
from tkinter import Tk, Label
root=Tk()
def key_pressed(event):
w=Label(root,text="Key Pressed: "+event.char)
w.place(x=70,y=90)
root.bind("<Key>",key_pressed)
root.mainloop()

Is it possible to alter binding order of a Tk/Tkinter Listbox widget <<ListboxSelect>> event

As far as I understand, the "normal" binding events order of a Tk/Tkinter Listbox widget is (simplifying): <ButtonPress>, <<ListboxSelect>>, <ButtonRelease>
Is it possible to "change" the order so to have <<ListboxSelect>> event triggering after the <ButtonRelease> one?
I was trying using bindtags together with a custom "fake" bind_class for this but without getting the desired result so far...
Here's the code sample:
import tkinter as tk
root = tk.Tk()
l = tk.Listbox(root, name='custlist')
for e in range(55): l.insert(tk.END, 'L_item'+str(e))
l.pack()
l.bind('<ButtonPress>', lambda e: print("L: Click"))
l.bind('<ButtonRelease>', lambda e: print("L: ButtonRelease"))
l.bind_class("post-class-bindings", "<<ListboxSelect>>", lambda e: print("L: post-ListboxSelect"))
l.bindtags((l.winfo_pathname(l.winfo_id()),'Listbox','post-class-bindings', '.', 'all'))
Can you tell me if is it possible to obtain such a thing in this way or another?
Thank you
EDIT:
Thinking of it I realize I can't get it that way 'cause I guess
<ButtonPress>+<<ListboxSelect>> events are somewhat "chained" in their flow while <ButtonRelease> is something "untied", so that I should invoke/generate the <<ListboxSelect>> event at the end of the <ButtonRelease> callback to trigger it... That might work most of the times but... That's not what I was trying to get here... (Indeed, that would be just like "moving" the <<ListboxSelect>> event code to the <ButtonRelease> callbak...)
So, in the end, the question would be if is it possible to "chain" ButtonRelease together with ListboxSelect (in the same way as for ButtonPress)? ... And I guess something like that isn't possible
Is it possible to "change" the order so to have <<ListboxSelect>> event triggering after the one?
The only way to do that is to prevent the selection from changing on a button click. <<ListboxSelect>> isn't a direct result of a button click or a button release, it's a direct result of the selection having been changed. You can't have the selection change on a click and not have <<ListboxSelect>> be generated.
I don't quite understand what your real need is, but if you want to be notified of a selection change on the release of the button you can always emit your own custom virtual event in a handler for <ButtonRelease-1>, for instance, <<ListboxSelectAfterClick>>.
Thanks to Bryan Oakley's clarifications I came to a possible solution for this:
The main intent for me was to have the element
selection in the list to activate/trigger only after the mouse button being released.
import tkinter as tk
root = tk.Tk()
l = tk.Listbox(temp, name='custlist', selectmode='single')
for e in range(55): l.insert(tk.END, 'L_item'+str(e))
l.pack()
l.bind('<ButtonPress>', lambda e: "break")
def AfterReleaseSelect(event):
event.widget.selection_clear(0,tk.END)
event.widget.selection_set(event.widget.nearest(event.y))
#more stuffs here if needed...
l.bind('<ButtonRelease>', AfterReleaseSelect)
What I'm doing here, in practice, is preventing the button click to do its job, so that the listbox selection won't be triggering, and then wait for the mouse button being released to do the stuff.
Some final thoughts on this:
First of all, please notice: I added selectmode='single' parameter to the Listbox widget here as I think it wouldn't be worth to apply such approach when dealing with default ("'browse'-select") Listboxes. This is because, differently than "'browse'-select" Listboxes, with "'single'-select" Listboxes elements selection doesn't "follow" the mouse 'till the end, it gets "stuck" on the first-clicked-element, even if you end releasing the mouse button on a different item.
I must say, anyhow, this probably won't be worth most of the times 'cause you might simply:
avoid using selectmode='single' parameter, staying with the default listbox 'browse'-select-behavior;
"move" the code you would execute with a bind <<ListboxSelect>> to a bind on <ButtonRelease> (as far as this doesn't involve too much "twisting" on the rest of the code, of course...)

How to bind multiple keyboard buttons to a widget in Tkinter Python

I am trying to make a simplest calculator and I want to operate it with the keyboard. This is the file.
I want that whenever I press any number button or a sign button it insert to Entry widget and it does nothing if any button other than number button or sign button is pressed. I want to put all the code in the keyboardbutton function.
Sorry for less comments in the code. And thanks in advance for any help.
First, I made a list in __init__ that matched your self.lst but where all characters are strings:
self.STR_LIST = list(map(str, self.lst))
Next, I bound keypresses to your tkinter window, so that the keyboardbutton mehtod will be called whenever a key is pressed (also in __init__):
self.window.bind("<Key>", self.keyboardbutton)
Then this should work for your keyboardbutton method:
def keyboardbutton(self, event):
if event.char in self.STR_LIST:
self.insert(event.char)
When a key is pressed, an event is sent to this method and we just simply check if it is a valid character for entry, then call your insert method.
Let me know if this works for you.

Run function from Python 2 Tkinter button when pressed then run another when released

Hello I am trying to make a simple recorder in Python 2.7 using Tkinter as the GUI, I want to be able to record when the button is pressed then save the recording when the button is released, I know how to make the button and have already done so, but I don't know how to make it run a program when pressed and another when released, is it possible?
Also I'm not sure how to actually record from the microphone and save it using pyaudio, any help with this is appreciated but I'm sure I can figure this out myself when I have overcome the main issue.
You can bind an event to the click of the left mouse button <Button-1> and to the release of the left mouse button <ButtonRelease-1>. Here's an example:
import Tkinter as tk
root = tk.Tk()
def clicked(event):
var.set('Clicked the button')
def released(event):
var.set('Released the button')
var = tk.StringVar()
var.set('Nothing to see here')
label = tk.Label(root, textvar=var)
label.pack()
but = tk.Button(root, text='Button')
but.bind("<Button-1>", clicked)
but.bind("<ButtonRelease-1>", released)
but.pack()
root.mainloop()

Cursor event handling in python+Tkinter

I'm building a code in which I'd like to be able to generate an event when the user changes the focus of the cursor from an Entry widget to anywhere, for example another entry widget, a button...
So far i only came out with the idea to bind to TAB and mouse click, although if i bind the mouse click to the Entry widget i only get mouse events when inside the Entry widget.
How can I accomplish generate events for when a widget loses cursor focus?
Thanks in advance!
The events <FocusIn> and <FocusOut> are what you want. Run the following example and you'll see you get focus in and out bindings whether you click or press tab (or shift-tab) when focus is in one of the entry widgets.
from Tkinter import *
def main():
global text
root=Tk()
l1=Label(root,text="Field 1:")
l2=Label(root,text="Field 2:")
t1=Text(root,height=4,width=40)
e1=Entry(root)
e2=Entry(root)
l1.grid(row=0,column=0,sticky="e")
e1.grid(row=0,column=1,sticky="ew")
l2.grid(row=1,column=0,sticky="e")
e2.grid(row=1,column=1,sticky="ew")
t1.grid(row=2,column=0,columnspan=2,sticky="nw")
root.grid_columnconfigure(1,weight=1)
root.grid_rowconfigure(2,weight=1)
root.bind_class("Entry","<FocusOut>",focusOutHandler)
root.bind_class("Entry","<FocusIn>",focusInHandler)
text = t1
root.mainloop()
def focusInHandler(event):
text.insert("end","FocusIn %s\n" % event.widget)
text.see("end")
def focusOutHandler(event):
text.insert("end","FocusOut %s\n" % event.widget)
text.see("end")
if __name__ == "__main__":
main();
This isn't specific to tkinter, and it's not focus based, but I got an answer to a similar question here:
Detecting Mouse clicks in windows using python
I haven't done any tkinter in quite a while, but there seems to be "FocusIn" and "FocusOut" events. You might be able to bind and track these to solve your issue.
From:
http://effbot.org/tkinterbook/tkinter-events-and-bindings.htm

Categories

Resources