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.
Related
I am trying to implement a little application that logs in a user and the user after log in can add/update/delete contents to/of a textfile. Here's a rough sketch of the code I have so far:
class admin():
def __init__(self):
self.app = Tk()
.
self.name=StringVar()
update = Button(self.app,....,command=self.update)
.
.
.
def update():
#Function to take different entries using Entry widget of tkinter in another window
anotherapp = Tk()
nameentry = Entry(anotherapp,textvariable = self.name)
submitbutton = Button(anotherapp,....,command=submit)
.
.
def submit():
#Opens a file and adds entries to a textfile.
namevar = self.name.get()
# code to append to file
To explain the above, I have a class admin. Creating an instance of this class would open a window with buttons that say create, update, delete and so on. On clicking one of the buttons, the respective functions (defined in the same class) would be called (I use lambda: in case the function has arguments, but so far, it doesn't).
So in the code I've mentioned, say I click on the Update button, it should call the update function which opens another window and takes the text that has to be updated in the text file (via the Entry widget). So according to the code it'll update the value of name. On clicking submit, the function submit uses .get() to get the string value of name, and appends it to the text file.
The code executes with no error but it DOES NOT read the input from the user. Blank lines get appended to my textfile when I click on the submit button.
Now I don't understand why this isn't working. The name variable is defined in init and can be updated by the functions of the same class. I have tried a lot of things to make this work, including adding parameters in the button commands, defining name elsewhere, etc. Even though I've solved the error, I get the same result: the file gets appended with blank lines. I've also tried to make name a class variable but that doesn't work since it is declared using StringVar() which needs it to be part of a tkinter window. I think I've also tried nesting submit function inside the update function, but I don't know why that didn't work out or if I hadn't implemented it correctly.
I don't know if it has to do with the working of tkinter's StringVar() and .get() function.
I can't think of any other way to implement the situation I have at hand. I am open to taking suggestions on changing the structure of the code, as long as it is not something major major and manages to achieve the functionality that I've described.
I am sorry if I've missed something basic, cause I've only started trying out OOP in python recently. And thanks in advance for any help.
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.
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)
I'm trying to work on a GUI done in pyqt. I'm trying to create a pop-up window has a textbox where a user can type/set the user's id (1-99) and then click an 'ok' button to set it and close the window.
This is what I have so far.
def viewProfile(self)
profBox = QMessageBox()
QMessageBox.about(self, 'Profile', "///Text box where can type User ID:// ",
QMessageBox.Ok)
I am not sure how to generate the textbox.
Also, if I want to display the integer value or string of a variable in my message window /box do I just leave it out of quotation marks but include it? What's the syntax for it?
Thank you!
You want to use a QInputDialog. This has a bunch of static methods which generate a complete dialog, and return the selected integer when the user clicks OK. This means you don't need to worry about creating a dialog object, adding widgets and buttons, etc.
So you would want to call:
parent_window = self #probably..., depends on your code
minimum_value = 1
maximum_value = 99
default_value = 1
title = "Profile"
message = "Select your user ID"
user_id, ok = QInputDialog.getInt(parent_window, title, message, default_value, minimum_value, maximum_value)
When the QInputDialog line of code runs, a dialog will be presented to the user. When the user clicks OK or Cancel, the entered user_ID will be placed in user_id and ok will be a boolean value that indicates whether the OK button was clicked (True if the OK button was clicked, False if the cancel button was clicked)
If you want to place an integer in the message, you could do something like:
message = "Select your user ID. An integer I want you to know about is %d. I hope you find that useful."%my_integer
But that is really a Python string formatting question, which you should research separately. In short, in my example you can display one string. How long, that string is, is up to you (it can be multiple lines, have new line characters, etc)
You should use QDialog. That way you can customize it the way you want (add textbox, button...)
Take a look at my answer here, basically it's log-in dialog created in QTDesigner, but you can create it with code since it's way more simplier
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().