I am trying to assign different functions to the clicked signal of a button depending on the activated value of a combo box with PyQt5.
Here is how I am trying to do it:
self.filterComboBox.activated[int].connect(self.filterComboChange)
def filterComboChange(self,option):
if(option==1):
self.filterAddButton.clicked.connect(self.onClickFilterAddButtonAge)
elif(option==2):
self.filterAddButton.clicked.connect(self.onClickFilterAddButtonFormat)
def onClickFilterAddButtonAge(self):
#some lines of code
def onClickFilterAddButtonFormat(self):
#some lines of code
I am selecting the first option in the combo Box, I push the button, function 1 runs fine
After that when I am pushing the button with the other option selected, before the second function being run, the first function runs.
Can anyone tell me the reason for this or tell me what I am doing wrong?
If signal is already connected, you need to disconnect it first before connecting it again.
def filterComboChange(self,option):
try:
self.filterAddButton.disconnect()
except:
pass
if(option==1):
self.filterAddButton.clicked.connect(self.onClickFilterAddButtonAge)
elif(option==2):
self.filterAddButton.clicked.connect(self.onClickFilterAddButtonFormat)
Related
I want to use KivyMDs FloatingActionButtonSpeedDial, with something different happening depending on which stack button is pressed. Right now, I'm just trying to print which button was pressed.
I've found outdated information from tutorials, but it looks like the current way to set a function on the button press is:
on_press_stack_button: root.callback(self)
then in my .py file I have
def callback(self, instance):
print(instance.icon)
but no matter which stack icon I choose, the result that's printed is always 'plus' (the root icon)
I'm guessing this is because I'm passing self into the callback function, but what else am I supposed to pass to access the actual button that's clicked? I can't find any examples in the docs, and all the tutorials I find say to use
'''
callback: callback
'''
instead of on_press_stack_button:
but using callback doesn't print anything at all.
Any help is greatly appreciated!
When you want to select an item in a Treeview, you usually use the double-click:
def print_element(event):
print(my_treeview.selection()[0])
my_treeview.bind("<Double-1>", print_element)
Today I tried to do the same but using a single click instead:
my_treeview.bind("<Button-1>", print_element)
But it wouldn't work. The output was just an empty tuple.
I started to search online for an explanation... why is it not working?
EDIT:
My goal was actually to do something every time a treeview item was selected.
I proposed a solution myself using the identify() function of Tkinter
Another user proposed to use the Tkinter callback <ButtonRelease-1> which is much more appropriate
Finally, a third user focused his answer on using the Tkinter callback <<TreeviewSelect>>, which is for sure the best option
The reason it doesn't work the way you expect is because your custom single-click binding happens before the default behavior. So, when your single-click is processed, that happens before an item is selected. The second time you click, your function will print the previously selected item.
If you want to have a function called when an item is selected, you should bind to <<TreeviewSelect>>, which will fire immediately after the user selects an item with a single click or via the keyboard.
The default behavior of a treeview supports selecting multiple items at once, so the following code will print out the text of all of the selected items as a list, even if only a single item is selected. You can, of course, modify this to only print out the first selected item if you so desire.
def print_element(event):
tree = event.widget
selection = [tree.item(item)["text"] for item in tree.selection()]
print("selected items:", selection)
tree.bind("<<TreeviewSelect>>", print_element)
It is because the selection is not set yet when the <Button-1> (it is the same as <ButtonPress-1>, i.e. when the mouse button 1 is pressed and not released) event callback is called.
You should bind on <ButtonRelease-1> or <<TreeviewSelect>> instead as the selection is set when the event callback is being executed.
Why it doesn't work
When you click an item in a treeview, that item is still not in a SELECTED status in the moment the callback is activated. You are changing the status in that very moment.
Using a double-click, the first click change the status, and at the second click you are activating your callback, so the status has already been changed.
How can it work
Kudos to this website
In short,
def print_element(event):
print(my_treeview.identify('item', e.x, e.y))
my_treeview.bind("<Button-1>", print_element)
This time, print_element() will check the coordinates of the mouse, and will discover the selected item check what is under the mouse. Nice and clean!
(Thanks in advance if you decide to answer. Sorry If I am not able to describe the content of the Application clearly.)
I am currently making Desktop Application using Tkinter Python for my gui interface. I am having a problem related to the flow of the Application.
My Application
Main Page of my application has form designed with some textboxes and checkboxes. Check button work as True or False Condition, where each check button refers to whether or not a specific function has to be executed or not.
To store the values of the check button, the dictionary is maintained with keys as LabelName and values as True/False value.
Checkbox code
f1=tk.BoolVar() #People tend to use IntVar() but i prefer BoolVar()
ttk.Label(text="func1")
ttk.Checkbutton(parent, variable=f1)
f2=tk.BoolVar()
ttk.Label(text="func2")
ttk.Checkbutton(parent, variable=f2)
-------other such CheckButtons------------------
There's a submit button in the form on pressing which all the data entered into textbox along with these check buttons. Based on true-false values, functions are called which is handled by if-else conditions.
#submit button
ttk.Button(parent,text="Submit",command=onsubmit)
###########
def onsubmit():
----------statements to read data--------------
dict['func1']=f1
dict['func2']=f2
#other statements
-----------------------------------------------
if dict['func1']:
func1()
if dict['func2']:
func2()
---other if-else conditions---
Each function is individual module which consists of either form, or frame with data or matplotlib graphs for visualization of data and to do other operations on data and graphs which are placed on root window frame.
My problem
I want the user to control the flow by giving them the next button after every function is executed and then move onto the execution of the next function based on his input of the check button. The program should wait until the User presses the next button and after they press the next button, it should execute the next function and then wait again for the next button.
One of the solution:
Using fig.waitforbuttonpress() was the solution. But I didn't find it reliable. Because even mouse click could skip the function execution. But I need to specifically assign a button through which the user can select when to proceed to the next function.
I am not sure if I understood what your code does, but you could do it something like that I guess:
next_button = ttk.Button(parent,text="Next",command=func1)
...
def func1():
#do your stuff here
next_button.configure(command=func2)
Then you would have to add the last line of code to all the functions to always reassign the button.
Another way could be:
process = 0
next_button = ttk.Button(parent,text="Next",command=next)
def next():
global process
process += 1
if process == 1:
func1()
elif process == 2:
func2()
...
elif *last_function_reached*:
process = 0
I am writing a program using tkinter, but I do not understand how it works. Normally, code is executed top-down, but with tkinter it obviously does not.
For example, I have bound a function to the left mouse button, and this function is executed every time I click the button. But how is the other code around that treated? My problem is that I in the start of my program initialize a variable that is used as an argument in the bound function, and then it is changed in the function and returned. But every time the function is called, the variable seems to be reset to its initial value.
Does anyone know why this is?
I have it written like this:
var = "black"
var = c.bind("<Button-1>", lambda event: func(event, arg=var))
The function "func" changes var and returns it, but the next time I press the button the variable is always "black".
Thanks in advance!
Tkinter does indeed run top down. What makes tkinter different is what happens when it gets to the bottom.
Typically, the last executable statement in a tkinter program is a call to the mainloop method of the root window. Roughtly speaking, tkinter programs look like this:
# top of the program logic
root = tkinter.Tk()
...
def some_function(): ...
...
some_widget.bind("<1>", some_function)
...
# bottom of the program logic
root.mainloop()
mainloop is just a relatively simple infinite loop. You can think of it as having the following structure:
while the_window_has_not_been_destroyed():
event = wait_for_next_event()
process_event(event)
The program is in a constant state of waiting. It waits for an event such as a button click or key click, and then processes that event. Conceptually, it processes the event by scanning a table to find if that event has been associated with the widget that caught the event. If it finds a match, it runs the command that is bound to that widget+event combination.
When you set up a binding or associate a command with a button, you are adding something to that table. You are telling tkinter "if event X happens on widget Y, run function Z".
You can't use a return result because it's not your code that is calling this function. The code that calls the function is mainloop, and it doesn't care what the function returns. Anything that gets returned is simply ignored.
Hi I need to do this because, I am making a matching / memmory game, and there has to be a button (Totally separated from the ones on the current game) that when I press it, it has to show the matching cards automatically without having to touch the buttons with the mouse.
Is there a "press" function or something like that for pressing the button?
Thanks! :)
As Joel Cornett suggests in a comment, it might make more sense to simply call the callback that you passed to the button. However, as described in the docs, the Button.invoke() method will have the same effect as pressing the button (and will return the result of the callback), with the slight advantage that it will have no effect if the button is currently disabled or has no callback.
If you also want visual feedback for the button you can do something like this:
from time import sleep
# somewhere the button is defined to do something when clicked
self.button_save = tk.Button(text="Save", command = self.doSomething)
# somewhere else
self.button_save.bind("<Return>", self.invoke_button)
def invoke_button(self, event):
event.widget.config(relief = "sunken")
self.root.update_idletasks()
event.widget.invoke()
sleep(0.1)
event.widget.config(relief = "raised")
In this example when the button has focus and Enter/Return is pressed on the keyboard, the button appears to be pressed, does the same thing as when clicked (mouse/touch) and then appears unpressed again.