Creating a GUI Calculator in python similar to MS Calculator - python

I need to write a code that runs similar to normal calculators in such a way that it displays the first number I type in, when i press the operand, the entry widget still displays the first number, but when i press the numbers for my second number, the first one gets replaced. I'm not to the point in writing the whole code yet, but I'm stuck at the point where when I press the 2nd number(s), the first set gets replaced. I was thinking about if key == one of the operands, than I set the num on the entry as variable first, then I do ent.delete(0,end) to clear the screen and ent.insert(0,first) to display the first num in the entry widget. Now I don't know what to do to clear the entry widget when the 2nd number(s) is pressed.

What you need here is a concept of state. Each time a key is pressed, you check the state and determine what action to take.
In the initial state, you take input of numbers.
When an operand button is pressed, you store the operand, and change the state.
When another number is pressed, you store the number, clear the numeric input, and start the number input again.
Then when the equals button is pressed, you perform the operation, using your stored number and operand with the current number in the numeric input.
Note that with a dynamic language like Python, instead of using a variable and if statements to check the state, you can just change the function that handles key/button pressed depending on what the state is.

Related

TableWidget "Enter" keypressed current text

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;

How do I update the data associated with a QListWidgetItem from the QListWidget in PyQt?

I have a QListWidget that has 10 QListWidgetItems. When each of those QListWidgetItems is created I do something like this:
item = QtGui.QListWidgetItem("Text to Show")
item.setData(36, "A specific value that is used later")
self.ui.my_list.addItem(item)
Now, later in the application, after a user clicks a button, I want to update the text "A specific value that is used later", for the item that is selected. I have attempted to do this
ndx = self.ui.my_list.currentRow()
self.ui.my_list.item(ndx).setData(36, "Updated!")
The problem is, this doesn't work. It doesn't throw any errors, but the data is just gone. In my button press signal I have this code to see the value before and after the reassignment:
ndx = self.ui.my_list.currentRow()
print "Before:", self.ui.my_list.item(ndx).data(36).toPyObject()
self.ui.my_list.item(ndx).setData(36, "Updated!")
print "After:", self.ui.my_list.item(ndx).data(36).toPyObject()
This outputs:
Before: A specific value that is used later
After:
How can I properly change the data so that it is saved back to the QListWidgetItem?
You may want to check that the role value your using is a valid user role, otherwise it may be altered internally. I write in c++, but I use the QListWidget and QListWidgetItem(s) frequently, and this was a problem I encountered early on. I imagen that the functionality is similar regardless of the language. According to the documentation here, the first user role that can be used is 0x0010. So to tie it to your example, you might try the following:
item.setData(0x0010, "A specific value that is used later")
For additional item roles you would use 0x0011, 0x0012, 0x0013, etc.

How to decide which radio button to click

I'm trying to create variables at the top of my script so that users can manipulate it's values without needing to go down into the code. E.g.
# Airports
FROM = "Leeds Bradford"
TO = "Antalya"
...//Later in code
depart_from = driver.find_element_by_id("departure-airport-input")
depart_from.clear()
depart_from.send_keys(FROM)
depart_from = driver.find_element_by_id("destination-airport-input")
depart_from.clear()
depart_from.send_keys(TO)
One thing I can't seem to get my head around is where a user may have a choice between selecting one radio button or the other. At the moment it's rigid where I say click this type of radio button.
return_flight = driver.find_element_by_id('return-flight-selector').click()
But I want the user to decide which radio button to select between the above and below:
one_flight = driver.find_element_by_id('oneway-flight-selector').click()
Is there a way I can do this? I want to assign a number to a radio button, so that all the user needs to do is change a number to get either one or the other? Like for example having a variable call FLIGHT_TYPE = ? ? is either "0" meaning select the return_flight radio button, or "1" meaning select the one_flight radio button.
Sure make a boolean variable and call it, for instance, ONE_WAY. Then, depending on it's value decide which item to click:
ONE_WAY = True
if ONE_WAY:
driver.find_element_by_id('oneway-flight-selector').click()
else:
driver.find_element_by_id('return-flight-selector').click()

Psychopy builder expt. - how to add live updating text on screen

I am creating an experiment using Psychopy builder.
The participant is presented with an image containing numbers, e.g. 10 and 20.
They enter what they think is the mean of the numbers, 15 in this case, and then press the spacebar to move on to the next image.
I am trying to have it so there is a display/box on screen that shows them their entry, as with larger numbers in the hundreds of thousands and millions I think they might lose track of what they have pressed.
The ability to change their entry would be excellent also, but really I am most interested in them being able to see it on screen.
In builder I can't find a way to do this, and the ratings scale is not appropriate for huge numbers.
I found these solutions in code to do something that sounds like it:
http://www.psychopy.org/wiki/home.php/Snippets/LiveUpdatingText
However when I try to add them using the code insert function , or just adding them to the compiled script the screen locks up when I try to run the experiment. I am a novice at python, and am not sure where to start fixing this. Is what I'm trying to do possible?
I'm happy to provide some example code from the compiled builder experiment.
Thanks in advance!
Those code snippets are designed for Coder, where you control everything that is happening and when. The same thing can be done in Builder, but you will have to amend the code to fit in with Builder's event loop cycle. i.e. Builder does certain things at the start of an experiment, on every trial, on every screen refresh and so on. So you can't just insert this sort of code without modification, because, for example, it attempts to wait indefinitely for a keypress. Builder meanwhile, is checking the keyboard every screen refresh (typically at 60 Hz), so if you try to wait indefinitely for a keypress in code, you'll be halting Builder from doing everything else it needs to do.
In essence, you just need to break up the code into snippets that go in the appropriate tab in a Builder Code Component (for code to be executed at experiment start, on each frame, and so on), and avoid indefinite functions like event.waitKeys() in favour of instantaneous checking via event.getKeys()
e.g. to adapt the second example from Jonas Lindeløv, in the "Begin Routine" tab, put:
chars = list('0123456789.') # the valid characters
meanText = '' # start with an empty answer on each trial
In the "Each Frame" tab, put something like:
response = event.getKeys() # get a list of keys pressed at this instant
if len(response) > 0: # if there was one,
key = response[0] # just convenient shorthand
if key in chars:
meanText = meanText + response[0]
elif key == 'space':
meanText = meanText + ' '
elif key == 'backspace' and len(meanText) > 0:
meanText = meanText[:-1]
elif key == 'return':
thisExp.addData('Answer', meanText) # save the response
continueRoutine = False # finish this trial
# update the appropriate text stimulus with the current response value:
insertNameOfYourTextStimulusComponent.text = meanText

How to check the state of a robot button using python?

i'm currently developping a program that runs on a robot. The program needs to add positions to a list but you have to push a button to add a new position. This has to be inside a while loop. But when i press the button the function repeats itself multiple times instead of just 1. Here is the part of code:
while not self.done():
if self._io_left_lower.state:
self._gripper_left.open()
elif self._io_left_upper.state:
self._gripper_left.close()
if self._io_right_lower.state:
self._gripper_right.open()
elif self._io_right_upper.state:
self._gripper_right.close()
if self._io_left_nav.button0:
print("repeats")
#self._mapping.append([self._limb_left.joint_angles(), self._gripper_left.position()])
if self._io_right_nav.button0:
self._mapping.append([self._limb_right.joint_angles(), self._gripper_right.position()])
if self._io_left_nav.button1:
self.stop()
As you can see when the self._io_left_nav.button0 is pressed it will now just print 'repeats' several times but it has to to be printed just onces. same for the self._io_right_nav.button0.
If button0 is a physical button and your loop is polling the button state then it is normal that many iterations run in the time your button is being pressed. You have several options to solve this situation, two of them are:
Do not use a loop check the button but hardware interruptions used to keep an updated representation of your state.
If you still want to use your loop, you should detect button state changes instead checking its current state at each iteration. That may require your program to implement a noise filter.
A very simple way to implement the second option is to have a button state variable with a timestamp associated: At each loop iteration, if the difference between the current time and the timestamp is big enought then you should check if the current state is the same than the one stored in the variable. If not then you have detected a change. In any case, at this point you should update your state-timestamp variable.
This is an example:
from time import time
prevState = (False,time())
while not self.done():
current = time()
if self._io_left_nav.button0 and (current-prevState[1])*1000>2: #For example, 2 ms
if self._io_left_nav.button0 != prevState[0]:
print("repeats")
prevState = (self._io_left_nav.button0,time())
I presume that's some kind of flag, that the button was pressed.
If you don't clear the state, the condition in the if statement will evaluate true. Again, and again....

Categories

Resources