Welcome!
This is the community forum for my apps Pythonista and Editorial.
For individual support questions, you can also send an email. If you have a very short question or just want to say hello — I'm @olemoritz on Twitter.
Another dialogue issue
-
I have a dialogue problem, and hope someone can help.
In a Model-View-Controller setup, my View has a TextLine and a TextViewWhen a line is typed, it passes to the controller, which echoes to the TextView.
All this works fine. (This is for a MUD-type adventure game)
The controller passes the line to a parser in the model.On certain inputs I want the model to get more data from the user via a FormDialog, which I can do easily. But the dialogue does not block the main loop. I’m using this code which I found on your site.
def myform_dialog(title='', fields=None,sections=None, ``` Insert Code Here ```done_button_title='ok'): global c sections = [('', fields)] c = dialogs._FormDialogController(title, sections, done_button_title=done_button_title) c.container_view.frame = (0, 0, 500,900) c.container_view.present('sheet') c.container_view.wait_modal() # Get rid of the view to avoid a retain cycle: c.container_view = None if c.was_canceled: return None return c.values
Obviously, I don’t know what I’m doing. I tried some combinations of @ui.in_background, but nothing helps. Any ideas?
-
@Tel Why did you not use the standard method dialogs.form_dialog?
-
And sometimes, I've to put @ui.in_background in front of each def calling the form_dialog
-
Are you trying to create a form which does NOT block?
The blocking is caused by wait_modal. I gather you want is to return a view, not a value. You can't return values unless you block, since values will not exist yet, until the user interacts. With a view, you can have delegate methods on the textfield/textview, which then call some other callback that you define
-
@JonB I do want it to block, but if I call it with another view still active, it does not block. You see I have the wait_modal call?
-
@cvp can you point me to an example? I think I am using the dialog form_dialog
The call is
result = myform_dialog(title='Link design', done_button_title='ok',fields=fields, sections=None) It seems that there might be a problem when another view is still active. I can send full code if you like...```=
-
Can you explain what your problem is? Are you getting an error? Or itbl doesn't show up? Are you calling your function from a callback of another UI ?
Are you trying to present a 'sheet' while another sheet is still there?
What might be helpful is to show a minimal example of a set of uis that display your issue. I.e you don't have to share your whole code, just mock up a textview and your actions, etc.
The trick, if you are trying to launch a dialog from, say, a textfield delegate, is that the delegate action must return before anything else can happen. That means, you need to show your form without a wait_modal, and instead must use a callback, maybe tied to will_close of your dialog. In some cases you may be able to use in_background, though a complication is that everything executed in_background all gets queued to the same thread, which can lead to strange things. Another approach that is more robust is to spawn your own thread. See for example this decorator
A better approach sometimes is to use a "shield view". @polymerchm pioneered this approach, nice shown in action here. This is a semi transparent view that gets added to your root view, but at the top of everything else, so no touches go down to your root view. But you can use it as a parent for dialogs.
-
@Tel I think that you will never receive a better explanation than @JonB 's one.
Sometimes, if a form_dialog needs to call another dialog, or even a console.input_alert, there are problems. In this case, I use the "shield" method, exactly like @omz does with the datepicker in its dialogs.py. -
@JonB thanks for that. It’s very helpful
I will try to put together a minimal example. But I think the direction you point is good.I am calling, from a delegate, a routine that calls another , say X, which put some up this form_dialog. The dialog appears, but the X thread continues before the form_dialog gets data. That is why I say the form dialog is not blocking.
The blue link dialogs.py did not work for me.
-
@Tel said:
The blue link dialogs.py did not work for me.
When you type xxxx.py, this forum put it in blue, even if there is no link 😢
-
@JonB here is a cut down version showing the problem. You will see that the calling thread continues while the dialog is still up.
import sys, dialogs import ui import console import controller global theView class MyView(ui.View): last_content_offset = (-1,-1) def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.make_view() self.value = None def make_view(self): self.tv= ui.TextView(title='textview1', frame=self.bounds.inset(10,10),editable = False, border_width=2, bg_color='white', flex='hw') self.update_interval = 1/60 self.tv.height = self.bounds.height-70 self.add_subview(self.tv) tf = ui.TextField(frame = self.bounds.inset(10, 10), text_color='red') #print (self.bounds) tf.frame=(10,240,self.bounds.width-20,40) tf.height =32 tf.delegate = self tf.flex = 'w' tf.begin_editing() self.add_subview(tf) def update(self) : self.tv.content_offset = (0, self.tv.content_size[1] - self.tv.height) if self.tv.content_offset[1] < 0: self.tv.content_offset = (0,0) #if self.tv.content_offset != MyView.last_content_offset : #print ('*',self.tv.content_offset, self.tv.content_size, #self.height) MyView.last_content_offset = self.tv.content_offset def feedback(self, st): self.tv.text += st +'\n' def textfield_did_change(self, textfield): self.value = textfield.text def textfield_should_return(self, textfield): st = textfield.text self.tv.text += '>'+ st + '\n' parse(st) textfield.text='' return True def delayed_close(self) : self.feedback('shutting down...') ui.delay(self.close, 5) def feedback(st): global theView theView.feedback(st) def startView(): global theView print('starting View') theView = MyView(frame = (0,0,800,300), bg_color='white') theView.present(style='sheet', animated=False) return theView #this routine copied from forum, without the decoration, the dialog never gets input, have to cancel Pythonista @ui.in_background def myform_dialog(title='', fields=None,sections=None, done_button_title='ok'): global c sections = [('', fields)] c = dialogs._FormDialogController(title, sections, done_button_title=done_button_title) c.container_view.frame = (0, 0, 500,900) c.container_view.present('sheet') c.container_view.wait_modal() # Get rid of the view to avoid a retain cycle: c.container_view = None print('from myform_dialog:',str(c.values)) if c.was_canceled: return None return c.values #this part actually in the model def parse(st) : fields = [{'title':'name','type':'text','value':st} ] result = myform_dialog(title='Link design', done_button_title='ok',fields=fields, sections=None) feedback(str(result)) print('from parse:',result) if __name__ == "__main__": console.clear() #show just ui startView() ```
-
@Tel no module controller, sorry
Édit: no need, commented
-
@Tel Please, Try this
result = dialogs.form_dialog(title='Link design', done_button_title='ok',fields=fields, sections=None) #result = myform_dialog(title='Link design', done_button_title='ok',fields=fields, sections=None)
-
@cvp that hangs up Pythonista
-
@Tel oups, I don't have that, please restart (NOT REINSTALL) Pythonista
-
@Tel said:
You will see that the calling thread continues while the dialog is still up.
The calling thread does a "print from parse" but I don't see it in console before I press ok in the dialog, thus that works, isn'it?
-
@cvp this is weird. It worked once, after I restarted. Now cannot repeat it, even after restart. Moreover, it seemed to affect Safari. I had to refresh the page before it allowed me to reply.
-
@Tel said:
it seemed to affect Safari. I had to refresh the page before it allowed me to reply.
Not sure of that, I have remarked such problems with this forum since some days.
-
@Tel I' e tried with and without @ui.in_background before def parse, no difference
-
In your "cut down" version, how are you sure that the calling thread continues while the dialog is still up?