I'm trying to make a trigger for the Ok button in my application
The current code I tried was this:
self.okPushButton.setShortcut("ctrl+Enter")
However, it doesn't work, which kind of makes sense. I tried looking up some key sequences here, but, again, a similar issue if I try with the shift or alt keys.
How can I trigger the OkButton with ctrl+Enter
According to the docs:
Qt.Key_Enter 0x01000005 Typically located on the keypad.
That is to say when you set Enter we refer to the key that is on the numeric keypad.
But if you want to use the default enter you must use Return.
self.okPushButton.setShortcut("Ctrl+Return")
# seq = QKeySequence(Qt.CTRL+Qt.Key_Return)
# self.okPushButton.setShortcut(seq)
Related
I am currently designing an experiment where the user has to press either “left” or “right” on a screen sequence which would be used in a later screen input.
Window 1:
Do you think that A or B will happen?
A: press left arrow key
B: press right arrow key
Window 2 has a code behind it something of the sort from below in order for variables to be output in the backend for future analysis.
if(‘left’ in keyDecisionResponse.keys):
something to happen
elif(‘right’ in keyDecisionResponse.keys):
something else to happen
However, if the user doesn’t press anything (which could happen if the user is not paying attention), I receive the error:
TypeError: argument of type ‘NoneType’ is not iterable
Experiment ended.
Therefore, I would like to automatically assign ‘left’ to ‘None’ in Window 1, something of the sort:
if (‘None’ in keyDecisionResponse.keys):
keyDecisionResponse.keys = ‘left’
It does not work. Also, I tried several things, but none of them worked.
Can you please help?
Thanks.
Check if keyDecisionResponse.keys is type NoneType then select default.
if keyDecisionResponse.keys is None:
keyDecisionResponse.keys = "left" # Or however you assign it
Also, make sure that you retain indentation and use proper quotation marks.
I am currently a novice in python and I'm trying to make a label switch from one image to another by clicking a next button. Here's my code:
from tkinter import *
def next1():
global slide
slide=1
if slide==1:
bglabel.config(image=bg1)
elif slide==2:
bglabel.config(image=bg2)
slide+=1
window.update()
window=Tk()
window.geometry("1500x750+0+0")
bg1=PhotoImage(file="backslide1.png")
bg2=PhotoImage(file="backslide2.png")
nextbutton=PhotoImage(file="next.png")
bglabel=Label(window, image=bg1)
bglabel.place(x=600,y=200)
nextbutton1=Button(window, image=nextbutton, bd=0, command=next1())
window.bind('<Button-1>', next1())
I sat for a good hour or so trying to tamper with the slide variable (trying to declare it before def, removing global, changing value, changing where slide+=1 is, etc) but one of two things always happens; either it's stuck on bg1 with the button clicking but doing nothing, or jumping straight to bg2. I've also tried splitting next1 into two different def's, one for variable tracking, one for switching bglabel, but still the same output. Please help.
(Also, will that window.bind be trouble as I continue to add buttons? If so please let me know how to do it correctly.)
As you mentioned, one 'error' that occurs is that the image immediately jumps to image bg2. This is the line causing that:
nextbutton1=Button(window, image=nextbutton, bd=0, command=next1())
More specifically, where you declare the command associated with the button:
command=next1()
With the enclosed brackets, you're calling the function next1 i.e. as soon as the button is created, run the specified function.
To solve this, just remove the pair of brackets:
nextbutton1=Button(window, image=nextbutton, bd=0, command=next1)
The same goes for your key binding. This way, the button/key now has a reference to the function - it knows what function to run and will run it when the specified action is performed.
More about the key binding...
When you use bind to assign a key to run a function, whatever function that is to be run needs to be made aware as such. Currently, the next function you are trying to bind is given no indication that it can be called using a keyboard button event. To fix that, we set a default parameter in next specifying the event:
def next1(event=None):
#rest of function code here
window.bind('<Button-1>', lambda event: next(event))
Setting a default parameter, event=None, basically means if no value forevent was passed to the function from whatever called it, set it to None by default (in that sense, you can choose to set it to whatever by default). Using lambda for the key bind in this way allows us to pass parameters to functions. We specify what parameter(s) we want to pass to the function and then specify the function, with the parameter(s) enclosed in brackets.
You need to provide the function, not the result of the function. So no parenthesis. Like this:
nextbutton1=Button(window, image=nextbutton, bd=0, command=next1)
Also remove the window.bind line, and your loop logic is broken. "slide" is always 1 since you set that in the function. Are you trying to cycle between the 2 images with every click? If so use itertools.cycle:
from tkinter import *
from itertools import cycle
def next1():
bglabel.config(image=next(bgimages))
window=Tk()
window.geometry("1500x750+0+0")
bg1=PhotoImage(file="backslide1.png")
bg2=PhotoImage(file="backslide2.png")
bgimages = cycle([bg1, bg2])
nextbutton=PhotoImage(file="next.png")
bglabel=Label(window)
bglabel.place(x=600,y=200)
next1() # set the first image
nextbutton1=Button(window, image=nextbutton, bd=0, command=next1)
nextbutton1.pack()
window.mainloop()
(totally untested since i don't have your images).
The issue
My issue is pretty simple, but I couldn't figure out how to cope with it easily even after some googling.
So I have a checkbutton:
self.but_val = IntVar()
self.but = Checkbutton(frame, text="text", variable=self.but_val)
This checkbutton triggers updates of some file path on the GUI:
self.but.bind('<ButtonRelease-1>',
lambda e: self.update_files_path(e), add='+')
In update_files_path(event), I need to get the value of the checkbutton to select the file paths to be displayed:
if self.but_val.get() == 0:
[...]
else:
[...]
The issue I have is that I get the value of the button before the clic.
And since the processing of file paths depends on different button values, I can't just use the opposite value.
My current work around
At the moment I have a function that is triggered before the clic and that save the state of the GUI:
self.but.bind('<ButtonPress-1>', lambda e,
self.save_design_opts_state(self.buttons_to_backup,
self.before_clic_vars_state), add='+')
Then in update_files_path(event) I call a function that infers the GUI state after the clic:
gui_state = self.get_gui_state(event)
This function is very annoying to implement, because I need to do a lot of things:
1- Check that the clic is really made on a button (to avoid a clic that starts on a button and end elsewhere!)
2- Get the value of the of all required buttons depending of their type
Is there an easier way to deal with this?
Thank you for your help!
Don't set your own bindings. Use the command option of the checkbutton. This option lets you specify a command to be run after the value has changed. There are other ways, but this is by far the simplest, most common way to solve your problem.
I am using tkinter for a GUI. I bound an event to an entry like so:
EntryFilePath.bind("<Key>", updateAmountOfPeople)
It works, but the problem is that it only updates when a key other than typing input is being pressed. Backspace triggers it, arrows trigger it, just not letters or numbers. I am looking for this functionality.
Other info that might be important:
PathFileName = StringVar()
EntryFilePath = Entry(topLeftMidFrame, textvariable = PathFileName, width=45)
EntryFilePath.pack(side=TOP, pady=32, padx=10)
How to make it trigger on any key?
EDIT: I found out that this only happens when it just got selected. It needs one of the "other" non [a-Z0-9] keys once, after that it is good to go. This is problematic though, in case people start immediately writing.
EDIT2: It might have to do with it having update delay.
The binding should work for every keypress -- if it's not, you're doing something somewhere else in your code to prevent it from working, or your testing is flawed.
If you want a function to be called whenever the value changes, you might want to consider setting a trace on the variable associated with the entry widget. The trace will fire whenever the value changes, no matter whether it's through keyboard input, pasting with the mouse, etc. It will not call your callback when the user uses the arrow keys or the return key, or any other key that doesn't affect the value.
For example:
def var_callback(*args):
print "the variable has changed:", PathFileName.get()
PathFileName.trace("w", var_callback)
It can be solved by changing
EntryFilePath.bind("<Key>", updateAmountOfPeople)
to
EntryFilePath.bind("<KeyRelease>", updateAmountOfPeople)
I'm using Tkinter for a small Python application. It has a set of ratio buttons, a text box, and a button. Is there a way to make it so the user can simply press Enter/Return on a keyboard and run the same function the button runs? The text box stays selected even when a radio is changed, so that won't cause any problems.
You should be able to bind an event handler to either the text box widget or the whole application that will be called when the event happens. Assuming you have a function to handle the event, something along the lines of:
widget.bind('<Return>', event_handler)
You can also bind a handler function at the application level by calling the bind_all() method of any widget, e.g.:
self.bind_all('<Return>', self.event_handler)
Note the key name is Return not Enter. See Key Names for a list of them all. You can also prefix the key name with a modifier like Shift- and Control- if desired.
There's a decent online reference for tkinter 8.4 here.