Unable to send signal from Button created in Python loop - python

I am trying to create a series of buttons in a loop. Each button gets an id number as it's text and when the button is clicked it is supposed to send the id number to a function that will open an archived order. At this time I just want to print the order number to prove that the signal works and each button is connected to the correct order number.
ui.cmdOpen = QtWidgets.QPushButton(ui.frOrdHist)
ui.cmdOpen.setGeometry(QtCore.QRect(269, line1Y, 61, 22))
ui.cmdOpen.setText(iOrderId)
ui.cmdOpen.setObjectName("cmdOpen")
ui.cmdOpen.clicked.connect(lambda button=ui.cmdOpen:displayOrder(ui, button))
def displayOrder(ui, button):
i = button.text()
print(i)
When I click the button, I get an error message that says "boolean object has no text attribute"
I tried passing the order number directly and it would print "False" so still a boolean. I don't know where the boolean is coming from, it must be something wrong in the signal.

The clicked signal always sends the checked state of the button. So this will overwrite your default button argument with a boolean value, which is why you get the AttributeError (i.e. because bool doesn't have that method). You should instead make the connection like this:
ui.cmdOpen.clicked.connect(
lambda checked, button=ui.cmdOpen: displayOrder(ui, button))
PS: another common source of this issue is the triggered signal of QAction. If you ever find your slots receiving unexpected inputs, it's always worth checking the Qt Docs to see if the signature of the signal has any parameters with default values - i.e. that look something like this:
void QSomeClass::someSignal(bool param = false)

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;

Python - checking for integers inside of a ui textfield

In the pythonista app for iOS I'm trying to check if a textfield in my ui has any numbers in it when I press on a button. When I use the same code on a string it works. When I use the code for textfield within a button's action it doesn't work. Please help? Here's what my code is like:
import ui
import console
def contains_digits(d):
for char in d:
if char.isdigit():
return True
return False
test='test3'
print(contains_digits(test)) #this works - it prints TRUE!
#below always prints failed even though it should print whatever is in the textfield?!
def button_pushed(sender):
if contains_digits(textfield1):
print(textfield1)
print('failed')
v=ui.load_view()
textfield1 = str(v['textfield1'].text)
v.present('fullscreen')
You’re setting the variable textfield to the field’s text before any text can be entered into the textfield1 TextField.
It will work if you just set textfield1 to v['textfield1'] and then get the .text out of it in your button_pushed function.
def button_pushed(sender):
if contains_digits(textfield1.text):
print(textfield1.text)
return
print('failed')
v=ui.load_view()
textfield1 = v['textfield1']
v.present('fullscreen')
This works because, instead of setting the text to what is in the field at startup, it waits until you have received notification that the field has been changed (assuming that is when button_pushed is called).
However, the best way to do this is to use the sender variable that button_pushed receives. Assuming you’ve set the TextField up so that textfield1.action is the button_pushed function, sender should be the TextField, so that you can do:
def button_pushed(sender):
if contains_digits(sender.text):
print(sender.text)
return
print('failed')
(Note that the way button_pushed is set up in your code, it will always print failed even if it also prints the semi-numeric text. You also need a return after the successful printing.)
I am aware of two ways to set a TextField to call a function (or method) as its action in Pythonista. The easiest is probably to set it within your code.
v=ui.load_view()
textfield1 = v['textfield1']
textfield1.action = button_pushed
v.present('fullscreen')
The other method is to set it within the UI file. When you have the TextField selected in the UI editor, and are looking at the settings for the TextField (as I write this, the “i” button in the upper right brings up the settings), the very bottom setting is “CUSTOM ATTRIBUTES”. Set the custom attributes to:
{'action':button_pushed}
Once you make either of these changes, then whenever the text field has finished editing (for example, by pressing “return” or by moving the focus to another field), that action will be called. Of course, if you do this and it turns out to be the behavior you want, you may wish to change the name of the function from button_pushed to something more descriptive of when or why the function is called.
You may also wish to change the name of the TextField from its default of “textfield1” to something more descriptive of its purpose as well, so as to make your code easier to follow once you have multiple fields to work with.

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.

PyQt : get a value from combobox when a button pressed

I use qt designer and convert it from *.ui to *.py, I want to make application for send and receive serial data,,
i use combobox to alow user for setting serial comةunication
self.ui.comboBox_2.addItems(['2400','4800','9600','19200'])
my question is how can i get value from combobo_2 to fill serial buadrate when I click a button
this is my code
self.connect(self.ui.comboBox_2, QtCore.SIGNAL('activated(QString)'),ser.baudRate())
and get an error
File "mainw.py", line 18, in press_2 self.connect(self.ui.comboBox_2,
QtCore.SIGNAL('activated(QString)'),ser.baudRate()) AttributeError:
'Serial' object has no attribute 'baudRate'
Your question about using a button to get the value from the combo box is different than what you are currently doing which is using a signal directly from when an value in the combo box was selected.
Your error is related to something else, it looks like in your signal you are calling a function "ser.baudRate()" but you have to pass in a function object, as it will pass in whatever "ser.buadRate()" returns. Which probably isn't a function. I'm not sure what that function returns. In any case, here is some ideas:
Using a button
If you want to use a button, then you would write something like this:
self.connect(self.ui.myButton, QtCore.SIGNAL('clicked()'), self.updateBaudRate)
def updateBaudRate(self):
# get value from combo box
rate = str(self.ui.comboBox_2.currentText()) # convert to string otherwise you will get a QString which is sometimes not friendly with other tools
ser.baudRate(rate)
Using the combo box signal
self.connect(self.ui.comboBox_2, QtCore.SIGNAL('currentIndexChanged(QString)'), self.updateBaudRate)
def updateBaudRate(self, rate):
ser.baudRate(str(rate)) # again convert to string as it my not accept a QString
You could use partial from the functools module or use a lambda instead of writing a function for the signal, but this is just for example.
You probably also want to use the "currentIndexChanged" signal instead of "activated" as "currentIndexChanged" will only emit when the value has changed, otherwise it will signal even if the user didn't select a different value in the combo box.

Get value from gtk.Entry in PyGTK

I am working on a PyGTK GUI project, and i would like to know, is there any way to get variable value from gtk.Entry?
text=gtk.Entry(0)
text.set_activates_default(True)
port = text.get_text()
This doesn't work as, the text box is empty by default, and get_text() returns empty string, any ideas?
This doesn't work as, the text box is empty by default, and get_text() returns empty string, any ideas?
Sounds like you're looking for getting the text after some user input. In order to do this, gtk uses signals that allow you to connect a user action to some function that will do something. In your case you want this function to get the text from the input. Because you haven't described the user interaction I'll give the simplest example. If you had a button
in your GUI that, when clicked, would grab whatever is typed in the entry at that moment, you'd do this:
button = gtk.Button( 'Click Me')
button.connect( 'clicked', on_button_click )
Then, you define the on_button_click function:
def on_button_click(self, widget, data=None):
port = text.get_text()
print 'Port: %s' % port
So with the sample code above, you'd have a button that, when clicked, grabs the text from your gtk.Entry.
Check out this link for a simple example on how to use signals in pygtk
Since your text field is by default empty, get_text() would return empty string.
Add a button callback function or some other function. So whenever that function is called, you would get the string from the Entry using
text.gtk_text()
You might want to use self here. since you'll be accessing entry in some other function and not in main thread, use
self.text=gtk.Entry()
self.text.set_activates_default(True)
def foo(self,widget,event): # some callback function
port = self.text.get_text()
print port
The retrieving method is the correct one, but right after the creation, the user can't yet have typed anyting into the field.
You would have to wait for the user to actually type something into the field, and afterwards calling get_text().

Categories

Resources