I have a click button that I want to change events when the button is pressed. A minimal version of the existing code looks like this:
# Event that happens the first time
def first_event(self):
button.setText("Second Event")
button.clicked.connect(second_event)
# Event that happens the second time
def second_event(self):
button.setText("First Event")
button.clicked.connect(first_event)
button = QtGui.QPushButton("First Event")
button.clicked.connect(first_event)
Unfortunately, instead of changing the event that happens, it simply adds and event to the clicked signal, meaning that the following happens:
First button press - calls first_event
Second button press - calls first_event and second_event
Third button press - calls first_event twice and second_event
etc...
My desired behavior would be to have the button change functions when it is pressed, so that the resulting behavior would be:
First button press - calls first_event
Second button press - calls second_event
Third button press - calls first_event
etc...
Is there a way to make it so that it changes the click event instead of adding a new one? Is there a way to remove events after the fact?
I found a way to separate old events from signals using the disconnect() method. Here is an edited version that accomplishes what I originally wanted to do:
# Event that happens the first time
def first_event(self):
button.setText("Second Event")
button.clicked.disconnect()
button.clicked.connect(second_event)
# Event that happens the second time
def second_event(self):
button.setText("First Event")
button.clicked.disconnect()
button.clicked.connect(first_event)
button = QtGui.QPushButton("First Event")
button.clicked.connect(first_event)
It's worth noting that instead of doing this, I eventually did what ekhumoro mentioned in the comments, and created a wrapper function with a flag to record the current state, and then call first_event() or second_event() based on the value of the flag.
Related
I am using python, Pyside2 on my interface.
I have a tableWidget and I want to get current text after press enter.
So I have below codes:
I add below function in to current page open:
self.ui.edit_table.keyPressEvent = self.KeyPressed
Then I add below function:
def KeyPressed(self, event):
if event.key() == QtCore.Qt.Key_Return:
print('Enter Key Pressed')
self.ui.edit_table.setEditTriggers(QtWidgets.QTableWidget.CurrentChanged)
print(self.ui.edit_table.item(0, 1).text())
newListValues = []
for i in range(0, 46):
newListValues.append(self.ui.edit_table.item(i, 1).text())
print(newListValues)
newListValues.clear()
When I change the value, and press the enter I see Enter Key Pressed but I couldnt see new value. But if I press the enter button one more without any changing, I can see new values in newListValue. Why the new value shows me with delay ?
For example item(0, 1) value is 5, when I change this value to 12 and press enter I couldnt see any changing in print(self.ui.edit_table.item(0, 1).text()) but when I press enter again I can see 12 value.
Why this happening ?
When pressing Return or Enter during the editing state, the data is not instantly submitted to the model.
The key press event is handled by the delegate editor (usually, the line edit) which will eventually validate or fixup the entered value and, finally, submit the data.
If you want to know when data has actually changed, connect to the itemChanged signal.
Also note that:
"patching" event handlers like this is discouraged, as often leads to silent errors or mishandled events (since the scope of the function is not the instance of the class that should handle the event); you either use an event filter, or a promoted widget;
you should always call the base implementation of the event handler, unless you're completely sure that you don't want to handle it; for instance, in your case your implementation completely prevents keyboard navigation or the possibility to enter the edit mode by pressing Return or F2;
I am using python to control an arduino.I want the python code to wait for the button to be pressed, and then move onto the next line.In the current code I have, the code sleeps for x seconds and checks if button has been pushed,if button is not pushed, it skips it.
This is my current code:
if bool(push_button2.read()):
print('Please press any button when done')
sleep(2)
if bool(push_button1.read()) or bool(push_button2.read()):
The problem with this is if push_button1 or push_button2 is not pressed, it will move onto the next code.So is there a way to make python wait for an input via the push button?
Thanks
You can use while for this:
while(!push_button2.read())
pass
Or you can even add s small sleep() here:
while(!push_button2.read())
sleep(0.01)
And finally, you can write your own functions:
# wait for one button
def wait_for_button(button):
while(!button.read())
pass
# wait for any button from a set
# usage: wait_for_any_button(button1, button2)
def wait_for_any_button(*args):
while !any(map(lambda b: b.read(), args)):
pass
# if you need a button index
def wait_for_any_button_i(*args):
while True:
for i, button in enumerate(args):
if button.read():
return i
https://arduino.stackexchange.com/questions/15844/pause-code-untill-a-button-is-pressed
So i am making a pygame program and for that i have written a GUI.py module. One of the classes is Button and one of the methods of that button is clicked, which basically checks if the button is being pressed. Initially i used pygame.mouse.get_pressed() to check for mouse press, but the problem i had with that is that it registered multiple presses within a single frame, which is not what i want.
def clicked(self):
mouse_pos = pygame.mouse.get_pos()# Gets the position of the mouse
mouse_pressed = pygame.mouse.get_pressed()# Checks if the mouse is being pressed
# checking if the mouse is already inside the button
if self.mouseover():
# mouse_pressed[0] returns true if the left mouse button is being pressed
if mouse_pressed[0]:
return True
return False
So i need to use events to check for mouse press. However, i am importing GUI.py to other modules, which are then imported to main.py. Becasue of this, i cannot import main.py to GUI.py. But main.py is where pygame.event.get() is being called in the main loop. I could call the method in other modules and pass in events as an argument, but i want to do that every single time i make a button.
Sorry if what i tried to explain is unclear, but here is what the question boils down to. Is there a way to make pygame.event.get() available to all the modules in my program independent of everything else?
The way i solved this in my pygame UI module was to store the previous frame click state, so if the mouse was clicked this frame and not last frame, its a click otherwise its being held down and nothing happens. (my module is a bit more complicated as it makes sure you clicked on it, then let go on it to count as a click)
if click and not previous_frame_click:
#clicked
if you are just using a function and not a class to do this, then maybe create a global variable
last_frame_click = False
def clicked(self):
global last_frame_click
mouse_pos = pygame.mouse.get_pos()# Gets the position of the mouse
mouse_pressed = pygame.mouse.get_pressed()# Checks if the mouse is being pressed
# checking if the mouse is already inside the button
if self.mouseover():
# mouse_pressed[0] returns true if the left mouse button is being pressed
if mouse_pressed[0] and not last_frame_click[0]:
last_frame_click = mouse_pressed
return True
last_frame_click = mouse_pressed
return False
EDIT: just noticed you said one of the classes, dont worry about above code, just use self.last_frame_click
When I had a similar issue I created an event manager module for it. Anything that wanted to be notified about events would register an event handler with the event manager, providing the events the handler was interested in and a event handler callback.
The event manager was handed the events from the event loop and it would check the events against the registered events. If there was a match then the event manager would call the associated event handler callback passing along the event as an argument to the callback.
It sounds more complicated than it really is.
I have an entry field, and as I type into the data field, I want a method, that updates a treeview widget to be ran. Currently, I can type in a search parameter, then press a 'search' button and it will run the method to search through the treeview to find specified clients, but I want to the treeview to be updating whilst typing into the entry, not by a button press
I am unsure as to weather this is possible, if it should be doing by binding keys or if there is a way using the event loop to achieve this?
See this SO post:
TkInter keypress, keyrelease events
Essentially:
from Tkinter import *
def keyup(e):
pass;
# e.char contains the pressed key if you need that info
# use your search function here
Edit (Sorry I forgot this):
You'll need to bind the keyup function to your widget with something like:
frame.bind("<KeyRelease>", keyup) # you can also bind to a search widget
I have a textBox on my WxPython GUI, where I am displaying a changing value (Which changes every 100 mS). I have two buttons - Button A, Button B.
Initial condition: Textbox has a value of between 2000-3000. Button A is enabled, Button B is disabled.
I need the following sequence of events to go on:
The user presses the Button A. After approximately 20 seconds or some user defined time (completely variable based on the user/ type of work he is doing), the textBox value goes under less 50.
Once the textBox value goes less than 50 - Button B should be enabled.
Currently this is my following code, where I am pressing the Button A - waiting for the textBox value to less than 50. Then enable the Button B - and it is not working. The button B is not getting enabled. I tried using other means, but they are leaving to an unresponsive GUI. My Button A is - DONE, Button B is START. textBox is pressure_text_control.
def OnDone(self, event):
self.WriteToController([0x04],'GuiMsgIn')
self.status_text.SetLabel('PRESSURE CALIBRATION DONE \n DUMP PRESSURE')
self.led1.SetBackgroundColour('GREY')
self.add_pressure.Disable()
while self.pressure_text_control.GetValue() < 50:
wx.CallAfter(self.StartEnable, 'Enabling start button')
#self.start.Enable()
def StartEnable(self):
self.start.Enable()
You haven't supplied sufficient code to be able to see what is going on.
We don't know for example if self.pressure_text_control.GetValue() < 50 is in fact less than 50, given that you say the value is changing every 100mS.
If your issue is really about the fact that the GUI becomes unresponsive, then investigate wx.Timer()
See:
http://www.blog.pythonlibrary.org/2009/08/25/wxpython-using-wx-timers/
The Timer class allows you to execute code at specified intervals, which allows you to process one or more periodic events (you can declare multiple timers), as long as they are not long or blocking processes, yet leave the GUI responsive.
mocked up as follows:
self.timer = wx.Timer(self)
self.Bind(wx.EVT_TIMER, self.check, self.timer)
def StartmyButton(self):
self.start.Enable()
self.timer.Start(100)
def check(self, event):
"check you input here and process any results"