Does anybody know how to create a text field using PyGTK that only accepts number. I am using Glade to build my UI.
Cheers,
I wouldn't know about a way to do something like this by simple switching a settings, I guess you will need to handle this via signals, one way would be to connect to the changed signal and then filter out anything that's not a number.
Simple approach(untested but should work):
class NumberEntry(gtk.Entry):
def __init__(self):
gtk.Entry.__init__(self)
self.connect('changed', self.on_changed)
def on_changed(self, *args):
text = self.get_text().strip()
self.set_text(''.join([i for i in text if i in '0123456789']))
If you want formatted Numbers you could of course go more fancy with a regex or something else, to determine which characters should stay inside the entry.
EDIT
Since you may not want to create your Entry in Python I'm going to show you a simple way to "numbify" an existing one.
def numbify(widget):
def filter_numbers(entry, *args):
text = entry.get_text().strip()
entry.set_text(''.join([i for i in text if i in '0123456789']))
widget.connect('changed', filter_numbers)
# Use gtk.Builder rather than glade, you'll need to change the format of your .glade file in Glade accordingly
builder = gtk.Builder()
builder.add_from_file('yourprogram.glade')
entry = builder.get_object('yourentry')
numbify(entry)
If you don't want to sanitize user input, avoid allowing text input entirely. If you're trying to collect hours and minutes, how about spin buttons or other widgets where you can limit the user's choice.
Check out the spinbutton example:
http://www.pygtk.org/pygtk2tutorial/examples/spinbutton.py
Convert your text to a number and in case it doesn't handle the error and set the text to an empty string.
You can generalize this to match a regular expression the way you want
try:
val = float(entry.get_text())
entry.set_text(str(val))
except ValueError:
entry.set_text('')
Related
I'm aware of the fact that text widgets are disabled using widget.config(state = tk.DISABLED), making the user unable to change the content of the widget. Content can be added before this statement is run using widget.insert(tk.END, text-to-add), but after that you'd have to alternate between the NORMAL and DISABLED states to add text content, using a command like this:
def add_text(widget, text):
widget.config (state = tk.NORMAL)
widget.insert (tk.END, text)
widget.config (state = tk.DISABLED)
Is there any other, more efficient way to do that?
Is there any other, more efficient way to do that?
No, there is not. That is the most efficient way to do what you want.
So I've created a GUI for a program I'm writing, and what I'm currently stuck on is the running of the calculations I want it to perform. I've done everything in Python 3.5, with a Kivy GUI build string to create the tabs (using tabbed panel and screen manager). I've got a button at the bottom of the tab to which this question pertains which says "Calculate" and should be taking the values of the text entries and operating them as part of the equation I want them to do.
Is the
.get
function going to be helpful in this case for doing this, or do I want to call more like:
class TabSys(TabbedPanel):
def calculate_psc_clicked(self):
#when they click the button which is id'd as "calculate_psc," this function
#will pull the values and perform the calculations
self.Cp_entry = self.Cp_entry.text
self.P_entry = self.P_entry.text
self.lhv_entry = self.lhv_entry.text
The above code is the TabSys class for my build string in kivy language, after it comes the
class nyce_meemApp(App):
def build(self):
return TabSys()
if __name__ == '__main__':
nyce_meemApp().run()
To actually run all the code. I don't want to inundate the question with code, so I'll leave it there, and I can put up any other pieces of code that anybody wants (if need be I can share the file).
Thanks
I want to keep track of the user modifying the company's forecast in my custom made app.
I created it using qt designer and PyQt4, and I'm using QSpinBox for the quantities (easy way to control range of values and masking the fields to be number only).
The problem I'm having is when I want to get the QSpinBox that triggered my function.
At this moment it's being triggered using valueChanged.connect but could be using anything else.
I can get the int in the spinbox but not the spinbox's name.
Thanks beforehand for the help!
SOLUTION
The QSpinBox element
self.Item = QtGui.QSpinBox(self.centralwidget)
self.Item.setObjectName(_fromUtf8("ItemName"))
Trigger
self.Item.valueChanged.connect(self.foo)
The function it calls
def foo(self,obj):
sender = MainWindow.sender()
print sender.objectName()
In this case "MainWindow" is my QtCore.QObject
AS the question tagged C++. I am answering in both C++ and pyQt4. I never worked in pyQt4. So please excuse me for syntax.
In the "valueChanged" slot use QObject::sender() to get the spin box which triggered it.
And then call "objectName()".
QObject* obj = sender();
QString objName = obj->objectName();
May be in python:
sender = QtCore.QObject.sender()
str = sender.objectName()
I'm working on a text-based game in Python using Tkinter. All the time the window contains a Label and a few Buttons (mostly 3). If it didn't have GUI, I could just use Pickle or even Python i/o (.txt file) to save data and later retrieve it. But what is the best way to tell the program to load the exact widgets without losing bindings, buttons' commands, classes etc.? P.S.: Buttons lead to cleaning the frame of widgets and summoning new widgets. I'm thinking of assigning a lambda (button's command) to a variable and then saving it (Pickle?) to be able to load it in the future and get the right point in the plot. Should I go for it or is there a better, alternative way to accomplish the thing? (If using lambda may work, I'd still be grateful to see your way of doing that.)
You need to save stuff in some kind of config file. In generel I'd recommend JSON and YAML as file formats also ini for ease of parsing.
Also, do not forget about the windows registry (portability lost then though).
My understanding was that you need a widget manager, to put them where you want and it is easy to pick up values.
Create a new class called Manager, make two functions, _setNewWidget, _deleteWidget, like this:
class Manager():
def __init__(self, *args, **kwargs):
objects = {}
def _createButton(self, frame, id, function, etc):
# object[id] = frame.Button(function, etc, ...) i dnt' know sintaxes, but this is the way
def _deleteWidget(self, id):
# object[id] = None or del(object[id]) same here
To get, just:
manager = Manager()
manager._createWidget("button_fase_one", frameTk, etc, etc)
manager.objects["button_fase_one"].changeFrame() # example
print(manager.objects["button_fase_one"].text)
In this way u can create objects and blit where u want.
To save data just make another function and save as json.
This is related to another question I found here that seems to be inactive for a few months, so I think it's worth asking again.
I have created a simple QDialog that has a QTextEdit and a QPushButton. This pops up in my application when a user right-clicks and selects the option to "add comments". I want them to be able to write free-form text and I'll just save whatever they write as a long string with no concern for new lines, etc.
When the user clicks the button, it executes code like this:
self.connect(accept_button,QtCore.SIGNAL('clicked()'),lambda arg=str(view_textedit.toPlainText()): self.updateGroupComments(arg))
def updateGroupComments(self,new_comment_str):
print "Updating user comment to have new string: " + new_comment_str
self.group_entry.list_of_user_comments[self.currentFrameCounter] = new_comment_str
This is not detecting the TextEdit text that is visible (it only detects whatever the text edit text is set to when it is created). How do I make a simple command that returns the currently visible text from a QTextEdit. Again, the function
toPlainText()
is not working correctly... it doesn't find the currently visible text, only whatever text was on screen before changes or additions started being made by the user.
If this can't be done without subclassing and appealing to cursor positions, it makes the whole thing seem worthless... so please keep suggestions only to those implemented without subclassing or manipulating cursors. It should be really simple and straightforward to just return all currently visible text... what am I missing?
Objects that are being bound to default arguments are evaluated at the definition time. The function is working correctly, it returns whatever was in the text field when it was executed. Your code simply calls it at the wrong moment. If you want to use lambda, then do:
self.connect(
accept_button, QtCore.SIGNAL('clicked()'),
lambda: self.updateGroupComments(str(view_textedit.toPlainText()))
)
Or make view_textedit an instance attribute instead, and do simply
self.connect(
accept_button, QtCore.SIGNAL('clicked()'), self.updateGroupComments
)
And change updateGroupComments to call self.view_textedit.toPlainText instead of taking an argument.
BTW, this is not PyQt specific, this is how Python works in general.
To illustrate my last comment, that lambda can very well be replaced with:
def slot():
self.updateGroupComments(str(view_textedit.toPlainText()))
self.connect(accept_button, QtCore.SIGNAL('clicked()'), slot)