I'm trying to update the text of and display a label inside of a for-loop in tkinter. This should happen after a second, according to the .after method.
def rightString(self, gro, string):
for z in string:
self.message2.configure(text="Good job, %s is a member of %s!" % (z, gro.getName()))
root.after(1000)
self.message2.grid()
print(z, " should be displayed!")
I hope this is enough info; I feel like there is something very basic I'm missing. The print function calls and displays each of the members of 'string' in IDLE. I don't understand why self.message2 does not display. It displays in other parts of the script which do not include 'after' methods.
I will post more of the code if it is necessary.
Thanks.
If you want to change the text of the label each second, then you have to schedule the function again with after:
def rightString(self, gro, string):
if string:
z = string[0]
self.message2.configure(text="Good job, %s is a member of %s!" % (z, gro.getName()))
root.after(1000, lambda: self.rightString(gro, string[1:])
print(z, " should be displayed!")
As I've said in my comment, calling grid() each time you change the text is not necessary.
Edit: To execute a different function when the processing of all strings has finished, you can add a call to it in an else block:
def rightString(self, gro, string):
if string:
# ...
else:
doSomethingElse()
It doesn't display because you are preventing the event loop from processing events, specifically the event that causes it to redraw the window on the screen. You need to restructure your code to avoid calling after with just a single argument.
Related
I am trying to implement a FormAction here, and I’ve overridden validate method.
Here is the code for the same:
def validate(self, dispatcher, tracker, domain):
logger.info("Validate of single entity called")
document_number = tracker.get_slot("document_number")
# Run regex on latest_message
extracted = re.findall(regexp, tracker.latest_message['text'])
document_array = []
for e in extracted:
document_array.append(e[0])
# generate set for needed things and
document_set = set(document_array)
document_array = list(document_set)
logger.info(document_set)
if len(document_set) > 0:
if document_number and len(document_number):
document_array = list(set(document_array + document_number))
return [SlotSet("document_number", document_array)]
else:
if document_number and len(document_number):
document_array = list(set(document_array + document_number))
return [SlotSet("document_number", document_array)]
else:
# Here it doesn't have previously set slot
# So Raise an error
raise ActionExecutionRejection(self.name(),
"Please provide document number")
So, ideally as per the docs, when ActionExecutionRejection occurs, it should utter a template with name utter_ask_{slotname} but it doesn’t trigger that action.
Here is my domain.yml templates
templates:
utter_greet:
- text: "Hi, hope you are having a good day! How can I help?"
utter_ask_document_number:
- text: "Please provide document number"
utter_help:
- text: "To find the document, please say the ID of a single document or multiple documents"
utter_goodbye:
- text: "Talk to you later!"
utter_thanks:
- text: "My pleasure."
The ActionExecutionRejection doesn't by default utter a template with the name utter_ask_{slotname}, but rather leaves the form logic to allow other policies (e.g. FallbackPolicy) to take action. The utter_ask_{slotname} is the default for the happy path in which it's trying to get a required slot for the first time. This default implementation of the action rejection is there in order to handle certain unhappy paths such as if a user decides they want to exit the flow by denying, or take a detour by chatting, etc.
If you want to implement the template to re-ask for the required slot using the utterance, you could replace the ActionExecutionRejection with dispatcher.utter_template(<desired template name>, tracker). However, this will leave you with no way to exit the form action without validation -- I don't know what your intents are, but perhaps you want to also incorporate some logic based on the intent (i.e. if it's something like "deny", let the ActionExecutionRejection happen so it can exit, it it's an "enter data" type of intent make sure it asks again).
I have an existing (WIP) pyramid project, with the simplistic forms all being done by hand. As the user requirements have been steadily increasing in complexity, I wanted to integrate deform forms to simplify my own maintenance/programming tasks.
My initial test was to try for an interfield form[1], the purpose being to ensure that a certain date predates another date in the form. Here's the simplified definition for the schema and validator:-
class Schema(colander.MappingSchema):
startdate = colander.SchemaNode(colander.Date())
enddate = colander.SchemaNode(colander.Date())
def validator(form, value):
if value['enddate'] - value['startdate'] < 0:
exc = colander.Invalid(form, 'Start date must precede End date')
exc['enddate'] = 'Must be after %s' % value['startdate']
raise exc
schema = Schema(validator=validator)
form = deform.Form(schema, buttons=('submit',))
I then pass the form to my mako template and call:-
${form.render() | n}
This renders the form properly, and my date selectors work (of course, after I had to mess around with loading the correct CSS and javascripts). However clicking submit doesn't do any validation (not even the basic 'you didn't enter a value'), instead it goes right back to my view_config.
What could I be missing?
[1] - https://deformdemo.pylonsproject.org/interfield/
It turns out deform doesn't handle the validation automatically, and I have to actually call validate, something like below:-
try:
appstruct = form.validate(request.POST.items())
except deform.ValidationFailure as e:
return {'form': e.render()}
In my game, I have an __init__ function which creates a set of seven entry boxes, like so:
self.string1 = StringVal()
self.entry1 = Entry(frame, textvariable = self.string1).grid(row = 4, column = 1, sticky = W)
This is copied six more times. This works.
At the end of the game, though, I want to delete the Entry box's text, using this code I found several places online:
self.entry1.delete(0, END)
I also tried using something else I found:
if self.entry1.get():
self.entry1.delete(0, END)
These both say that self.entry1 is a NoneType object, and has no method .get() or .delete(). Just to try things out, I substituted self.entry1.get() and self.entry1.delete(0,END) with self.string1.get(), etc. I also tried substituting .delete(0, END) with .delete(0.0, END). Neither of these worked either. I do not understand what I am doing wrong.
Thanks for your help!
When you do something like this:
self.foo = Button(...).grid(...)
... Then what gets stored in self.foo is the result of the call to grid(). This will always be None. You need to separate your widget creation from the loyout in order to save a reference to the created widgets.
Background: This is using page-object, and Rspec. The page, objects are setup correctly. Basically what is happening is its skipping the while statement and going directly to checking of the variable label exists on the page.
What it SHOULD do is check if the label variable is on the page and if not then wait 20 seconds and refresh the page then check again for up to 30 times and if it fails on the 30th time then it should fail all together. If it finds it then it should check again and pass it.
def check_label(label, current_page)
labels_filter_element.click
check_label_sla(label, current_page)
current_page.text.should include label
end
def check_label_sla(label, current_page)
t = 30
i = 0
while i < t
if current_page.text.should include label
return
else
sleep(20)
current_page.refresh
i += 1
end
end
end
I think what is happening is if current_page.text.should include label is always returning TRUE, but I'm not sure. If more info is needed please let me know.
I am making the following assumptions:
The behaviour you are seeing is that the page is first loaded, the labels_filter_element is clicked, the label is not on the page and the test fails immediately without refreshing the page.
label is a string
Given these assumptions, the problem is with the if-statement:
if current_page.text.should include label
When the if statement is executed, it will assert that the page includes the label:
If the page has the label, the code in the if will be executed (ie it will immediately return and the assertion in check_label will pass).
In the case that the page does not have the label, the assertion will throw an exception causing the test to fail immediately (ie the else code will not get executed). So the test is failing inside the check_label_sla method, not at the end of the check_label method (which makes it seem like the while loop is not working).
You want the if statement to check that the text is included, without making an assertion. Therefore you want:
if current_page.text.include? label
So your check_label_sla method would become:
def check_label_sla(label, current_page)
t = 30
i = 0
while i < t
if current_page.text.include? label
return
else
sleep(20)
current_page.refresh
i += 1
end
end
end
Or you could reduce it to:
def check_label_sla(label, current_page)
30.times do
return if current_page.text.include? label
sleep(20)
current_page.refresh
end
end
I have to modify a VB6 app and am repeatedly beating my head against a wall over control arrays.
I know that the event handler for the array includes its index value and I can set some variable there, but i should be able to directly access the selected radio button in an array of OptionButton. Currently I'm doing this
For i = 0 To optView.Count - 1
If optView.Item(i).value = True Then
currIndex = i
Exit For
End If
Next
Is this really my only option?
Yes, this is our only option. The control array object does not contain any selecting logic (which makes sense, as "selected" might mean different things for different controls). The only change I'd make is replacing the For with For Each.
Another way to do this that I have used. Write a function, and then call the function, passing in the control name, to return the index number. Then you can reuse this in the future especially, if you add it to a module (.bas).
Function f_GetOptionFromControlArray(opts As Object) As Integer
' From http://support.microsoft.com/KB/147673
' This function can be called like this:
' myVariable = f_GetOptionFromControlArray(optMyButtons) 'Control syntax OK
' myVariable = f_GetOptionFromControlArray(optMyButtons()) 'Array syntax OK
On Error GoTo GetOptionFail
Dim opt As OptionButton
For Each opt In opts
If opt.Value Then
f_GetOptionFromControlArray = opt.Index
Exit Function
End If
Next
GetOptionFail:
f_GetOptionFromControlArray = -1
End Function