using a string variable to control a textbox property - python

I have various textboxes on a form to enter numbers and want to have a single function which can check the entry and highight the box in red if incorrect rather than repeating the same code for each textbox.
Is it possible to set the name of the textbox (_FreqTextBox) as a variable so I can make this a generic function for each textbox. An example function is below. I've tried to find examples of this but no luck so far. Newish to Python so apologies if this is obvious.
def FreqTextBoxTextChanged(self, sender, e):
self._FreqTextBox.BackColor = System.Drawing.SystemColors.Window
IsNumber,text_value = self.CheckNumber(self._FreqTextBox.Text)
if (IsNumber == False):
self._FreqTextBox.BackColor = System.Drawing.Color.Red
return
IsNumber = self.NegativeValueMsg(text_value)
if (IsNumber == True):
self._FreqTextBox.BackColor = System.Drawing.Color.Red
return

Related

Dynamically add and remove list items in an IPython widget

I'm trying to achieve a basic todo list app in Ipython Jupyter Notebook using ipywidgets.
I can easily achieve the functionality of adding items to my list, however, I can't properly handle removing of existing items if the 'Remove' button is clicked. The entire code is run in a single cell.
import ipywidgets as widgets
from ipywidgets import VBox, HBox, Text, Button
from IPython.display import display
todo = []
def completed_sentence(sentence):
""" To display existing notes with a 'Remove' button """
sentenceField = Text(value=sentence)
removeButton = Button(description='Remove',
button_style='danger')
return HBox([sentenceField, removeButton])
def render_sentences(_):
""" To update the view """
global a,b
if a.value != '':
todo.append(a.value)
a.value = ''
todoWidget.children = tuple\
([VBox([VBox([completed_sentence(each)
for each in todo]),
HBox([a, b])])])
# Setting up a basic view- with an empty field and a button
a = widgets.Text(value='')
b = widgets.Button(description='Add')
b.on_click(render_sentences)
todoWidget = widgets.HBox([a, b])
display(todoWidget)
Now, in order to enable the removal of sentences, I update the definition of the function completed_sentence as follows:
def completed_sentence(sentence):
""" To display existing notes """
def remove_sentence(_):
global render_sentences
try:
if todo.index(sentenceField.value) >= 0:
todo.remove(sentenceField.value)
render_sentences()
except:
return
sentenceField = Text(value=sentence)
removeButton = Button(description='Remove', button_style='danger')
removeButton.on_click(remove_sentence)
return HBox([sentenceField, removeButton])
But now, this has the issue that its call to render_sentences is ignored! What is the optimal way to deal with such a kind of 'reactive' programming, if you will, using Ipython Widgets.
Updating the definition of completed_sentence seems to do the job. But it still remains a mystery why the original definition didn't work.
def completed_sentence(sentence):
def remove_sentence(_):
global render_sentences
try:
if todo.index(sentenceField.value) >= 0:
todo.remove(sentenceField.value)
except:
pass
render_sentences(_)
sentenceField = Text(value=sentence)
removeButton = Button(description='Remove', button_style='danger')
removeButton.on_click(remove_sentence)
sentence_view = HBox([sentenceField, removeButton])
return sentence_view

Simple GUI buttons and inputs

I am currently in an intro cs class and have a question about simple GUI and more specifically how to take a number (ex 6,7,8) input and when a button is pressed take the input number and determine if it is even or odd so far below is what I have and I get the error message that states: "button_handler() takes exactly 1 arguments (0 given)" Can someone explain to me what I am doing wrong?
import simplegui
global text_input
frame = simplegui.create_frame('Testing', 250, 250)
label = frame.add_label('Divisable by 6?')
def input_handler(text_input):
print "You entered,", text_input
def button_handler(num):
if float(num) / 6 == 0:
print "divisable by six"
else:
print "Not divisable by 6"
button1 = frame.add_button('divisable by 6?', button_handler)
inp = frame.add_input('Please insert number', input_handler, 50)
frame.start()
(BTW the formatting is weird when copied and pasted from code skulptor)
I am familiar with with tkinter and have not used simplegui, but from the error message, I can guess the problem.
button_handler is a callback that is called without any arguments when the button is clicked. But you define it with a parameter number. You have to re-write button_handler to get the number from the input some other way. I know how to do that with tkinter, but not for simplegui. Perhapsinput_handlershould write a global thatbutton_handler` can access.
In this line here:
button1 = frame.add_button('divisable by 6?', button_handler)
you are not feeding anything to button_handler. In other words, it has no arguments. But elsewhere in your code you mandate that button_handler has exactly one argument. So, you need to update your reference to button_handler in the line above to account for that fact.
(That's the fundamental bit, anyway: I don't want to comment on the rest of your code, since you say it is under construction.)
From the CodeSculptor documentation for frame.add_button():
The handler should be defined with no parameters
You can grab the content of an input field with get_text(). Here is a simple example that prints the content of an input field when a button is pressed:
import simplegui
def input_handler(text_input):
pass
def button_handler():
print inp.get_text()
frame = simplegui.create_frame("Demonstration of input and button", 300, 300)
inp = frame.add_input("Input:", input_handler, 100)
frame.add_button("Print", button_handler, 100)
frame.start()

How to return a drop-down value PyQT to another method Python

I am trying to create a PyQt Dropdown menu(combo box), whose value I need to pass to another function.
Here is a snippet of my code
def combo_box(self):
combo = QtGui.QComboBox(self)
...#Filled in code here
for i in range(0,len(arr)):
combo.addItem(arr[i])
#I want to get the value of the selected Drop-down content to be stored in value
value = combo.activated[str].connect(self.ComboValue)
print value
def ComboValue(self,Text):
print Text
return Text
When I print the variable Text in the ComboValue method it prints it right, but when I print value from the combo_box method it prints None.
I wanted to know why this happens, and is there an alternative to return the value to the other method?
combo.activated[str].connect(self.ComboValue) is signal and signal never return you anything back, so that's why you getting None. Take a look http://pyqt.sourceforge.net/Docs/PyQt4/new_style_signals_slots.html
You may use this value = str(combo.currentText()), but don't know you want this.
And change combo.activated[str].connect to combo.currentIndexChanged [str].connect to get your values properly
create the combobox, then wait till user activates an item:
def combo_box(self):
combo = QtGui.QComboBox(self)
...#Filled in code here
for i in range(0,len(arr)):
combo.addItem(arr[i])
combo.activated.connect(self.ComboValue)
# save it and wait for user to do something:
self.combo = combo
def ComboValue(self, Text):
# user has selected an item, save it:
self.value = Text
assert combo.currentText() == Text
... do something with it ...
Not tested so details may be wrong.

How to make Tkinter checkbuttons work individually and default as checked

I am trying to have a series of checkboxes which can be selected or not selected - then when the user presses the button, the letters allocated to the checkboxes should be added to an inputted string and then printed.
I am having 2 major problems;
The when the user presses a checkbox, all of the checkboxes are selected.
I would like to have the default being that all of them as checked, but I cannot find how to do this. If this cannot be answered, it is less important than the 1st problem, and hence doesn't matter as much.
This is my code so far;
import Tkinter
class MENU():
def __init__(self,NewData):
self.SCREEN = Tkinter.Tk()
self.NewData = NewData
self.Selection = {"A":1,"B":1,"C":1,"D":1}
self.A = Tkinter.Checkbutton(self.SCREEN,text="A",variable=self.Selection["A"]).pack()
self.B = Tkinter.Checkbutton(self.SCREEN,text="B",variable=self.Selection["B"]).pack()
self.C = Tkinter.Checkbutton(self.SCREEN,text="C",variable=self.Selection["C"]).pack()
self.D = Tkinter.Checkbutton(self.SCREEN,text="D",variable=self.Selection["D"]).pack()
self.BtnFinish = Tkinter.Button(self.SCREEN,text="Finish selection",command=self.FinishSelection)
self.BtnFinish.pack()
self.SCREEN.mainloop()
def FinishSelection(self):
SelectionString = ""
for n in self.Selection:
if self.Selection[n]:
SelectionString+=n
self.NewData+="\nQuestions\n"+SelectionString+"\n"
print self.NewData
MENU("")
If it matters at all, this is for Python 2.7.3. Additionally, my thanks, and also apologies to those of you who likely have to point out something incredibly obvious/basic, which, as a beginner for Tkinter, I have not realised.
You must use one of the Tkinter objects StrintVar, IntVar, BooleanVar or DoubleVar normally (StringVar) as the value of the variable argument. You can't use a normal python variable. You'll have to create an individual variable for each.
For example:
self.Selection = {"A": Tkinter.BoolVar(), "B": Tkinter.BoolVar(), ...}
self.Selection["A"].set(True)
...
Then, to get the value you'll need to use the get method:
value = self.Selection["A"].get()

Masking textfield for password in Maya UI using Python

I have created a UI in Maya to send some information for rendering in a mail. For that the user has to type different data including username and password. But when typing the password, it is visible like the other texts. Is there a way where the password could appear like dots or asterisks?? The script is written in Python. Below is the image of the UI.
You could set the changeCommand of the text field to a function that would save the text to a variable and replace the text shown with an asterisk for each character.
import pymel.core as pm
class myWindow():
def __init__(self):
self.password = ''
win = pm.window(title='Test')
lo = pm.columnLayout()
self.pswdField = pm.textField(changeCommand=self.hideText)
win.show()
def hideText(self, *args):
self.password = self.pswdField.getText()
self.pswdField.setText("*" * len(self.pswdField.getText()))
That's just one way and it's not very robust..but I would definitely look into Qt like Daniel pointed out.
For my code, I tried something like this:
self.Passwd.keyPressEvent = lambda event : self.encryption()
def encryption(self):
self.a = "*"
self.Passwd.setText(self.Passwd.text() + self.a)
This is just for encoding the characters with * as you type.
You still need to capture the input into a variable or something.
And somehow segregate the keys that are not allowed in the password.
hope it gives a start.
I found the below function best suited for the above problem:
self.Passwd = QLineEdit("Password")
self.Passwd.setEchoMode(QLineEdit.Password)
If Qt is too much trouble and you don't need it 100% reliable this might suffice. It's similar to the answer from Argiri, but it replaces text as it is typed, and appends each keypress to a variable.
import pymel.core as pm
class LoginWindow():
def __init__(self):
self.password = ""
self.win = pm.window()
lo = pm.columnLayout()
self.userField = pm.textField()
self.passField = pm.textField(textChangedCommand=self.obscure)
self.goButton = pm.button("Login", c=self.go)
self.win.show()
def obscure(self, *args):
new_pw = self.passField.getText()
if len(new_pw) > len(self.password):
self.password+=new_pw[-1]
elif len(new_pw) < len(self.password):
self.password = self.password[0:-1]
self.passField.setText(u"\u2022" * len(self.password))
def go(self, *args):
print ("u: {} p: {}".format(self.userField.getText(), self.password))
pm.deleteUI(self.win)
lw = LoginWindow()
Note that if the user tried to edit the middle of the password, or tried to type it in the wrong order the reported password would be mangled. I'm not sure if that's a problem in the real world.

Categories