Forum Archive

How can I manage controls over two views

satsuki.kojima

This maybe an easy question but I cannot figure out myself.
I want to show a pop-up view over my main view, selecting something on pop-up and send the selected thing back to the main view.
I made up a simple codes to show what I want to do.
By pressing a button, another small view is shown and putting some texts in a textfield and close it, I expect the texts will be put on the main view’s label. However it will not happen and only after closing the main view, I find in the console the texts are surely printed by print statement. Seems like control is not actually back to the program after closing the pop-up. How can I fix it?

import ui

class Test(ui.View):
    def __init__(self, frame):
        self.frame = frame
        self.bg_color = 'white'
        btn = ui.Button(frame=(100,100,100,30),
                                        title='Open pop', action = self.onBtn)
        self.label = ui.Label(frame=(100,200,400,30), border_width=1)
        self.add_subview(btn)
        self.add_subview(self.label)

    def onBtn(self, sender):
        self.label.text = 'calling pop'
        pop = Popup()
        pop.present('sheet')
        self.wait_modal()
        text = pop.get_text()
        self.label.text = text
        pop.close()
        print('after get_text', text )      

class Popup(ui.View):
    def __init__(self):
        self.frame = (100,100,400,600)
        self.bg_color = '#ededed'
        self.textbox = ui.TextField(frame=(100,100,200,30))
        self.add_subview(self.textbox)
        self.right_button_items = [ui.ButtonItem(title='close', action=lambda x:self.close())]

    def get_text(self):
        return self.textbox.text


if __name__ == '__main__':
    w, h = ui.get_screen_size()
    v = Test((0,0,w,h))
    v.present('sheet')
satsuki.kojima

@satsuki.kojima said:
Excuse my codes, but it always happens when embedding them from pythonista’s editor.
Tabs and under scores() of __init are gone when I posted. Please fix them before running my codes.

cvp

@satsuki.kojima said:

find in the console the texts are surely printed by print statement.

Sure.

cvp

@satsuki.kojima said:

self.wait_modal()
text = pop.get_text()

You try to get text after the pop has been closed.

JonB

You can't put a wait_modal inside a button action, because the ui thread blocks until the button exits.

You may be able to get your code to work by using @ui.in_background decorator on your action. I forget if wait_modal works with in_background.

There are other approaches using a "shield" view (a semi transparent empty view that covers your main view), which you can then display your dialog.

Also, check out the dialogs module to see if any of those are useful.

cvp

Try this

import ui

class Test(ui.View):
    def __init__(self, frame):
        self.frame = frame
        self.bg_color = 'white'
        btn = ui.Button(frame=(100,100,100,30),
        title='Open pop', action = self.onBtn)
        self.label = ui.Label(frame=(100,200,400,30), border_width=1, name='label')
        self.add_subview(btn)
        self.add_subview(self.label)
    def onBtn(self, sender):
        self.label.text = 'calling pop'
        pop = Popup(self)
        pop.present('sheet')
        self.wait_modal()
class Popup(ui.View):
    def __init__(self,main_view):
        self.main_view = main_view
        self.frame = (100,100,400,600)
        self.bg_color = '#ededed'
        self.textbox = ui.TextField(frame=(100,100,200,30))
        self.add_subview(self.textbox)
        self.right_button_items = [ui.ButtonItem(title='close', action=lambda x:self.get_text())]
    def get_text(self):
        self.main_view['label'].text = self.textbox.text
        self.close()

if __name__ == '__main__':
    w, h = ui.get_screen_size()
    v = Test((0,0,w,h))
    v.present('sheet')
cvp

Sorry @JonB our posts crossed them-selves

cvp

Plus @JonB advice, and all is ok

    @ui.in_background
    def onBtn(self, sender):
satsuki.kojima

@cvp

Yeah! your codes now put the texts back to the main view.

You can't put a wait_modal inside a button action, because the ui thread blocks until the button exits
Ok, so this was the problem.
and this is why the button still looks grey after closing the pop-up?

“@ui.in_background” didn’t work.
“using a "shield" view” > means using add_subview, right? Yes, I believe this would work for handing data.
dialog modules> I didn’t think about. I will check this.

Thanks for your many hints.

cvp

Or without needing pop class

    @ui.in_background
    def onBtn(self, sender):
        self.label.text = 'calling pop'
        f = dialogs.form_dialog('',fields=[{'title':'text','type':'text'}])
        if f:
            self.label.text = f['text']
cvp

@satsuki.kojima said:

@ui.in_background” didn’t work

Sure it works but be careful for your indentation

Édit: thanks to it, your button does not stay grey after

cvp

@satsuki.kojima and nicest to end, try this. Tap enter to close the text field

    @ui.in_background
    def onBtn(self, sender):
        self.label.text = 'calling pop'
        tf = ui.TextField()
        tf.frame = (0,0,100,32)
        tf.delegate = self
        tf.placeholder = 'type here'
        tf.present('sheet',hide_title_bar=True)
        tf.begin_editing()
        tf.wait_modal()
        self.label.text = tf.text
    def textfield_did_end_editing(self, textfield):
        textfield.close()

satsuki.kojima

@cvp
What I’m doing now is calling a view which is already made using view class (it’s like my original font-picker), so I would rather choose your first sample. I pass a label object when calling a popup view as an argument and it seems almost perfect except one thing.

In case of your first sample (which is without @ui.in_background,) when getting back from popup, the button looks stay grey even though I can still press the button. (so it just looks grey.) I thought putting “@ui.in_background” would solve it, but not really.
When putting “@ui.in_background” before def onBtn, after returning from popup the button now looks ok (I mean the color,) but the button never responds after it. Only after closing the main view, the button’s action occurs.

satsuki.kojima

@csv
Excuse my previous posting, I think I now solve this problem. Looking back to your advise, I no more need “wait_modal().” in your first sample, right? By deleting “wait_modal()”, it looks to work Ok now, thanks.

satsuki.kojima

not @csv,
@cvp
Excuse my type mistake.

cvp

@satsuki.kojima you're right. I did not see that, with wait_modal, the button seems to be inactive at close of textfield. I never test twice my scripts 🙄. Sorry for that.
But, without wait_modal, as the textfield is closed as soon we leave it, it seems ok. Perhaps that will be wrong at 5th test 😂. Wait and see.

cvp

@satsuki.kojima could you try this one please

import ui

class Test(ui.View):
    def __init__(self, frame):
        self.frame = frame
        self.bg_color = 'white'
        btn = ui.Button(frame=(100,100,100,30),
        title='Open pop', action = self.onBtn)
        self.label = ui.Label(frame=(100,200,400,30), border_width=1, name='label')
        self.add_subview(btn)
        self.add_subview(self.label)
        tf = ui.TextField(name='TextField')
        tf.frame = self.label.frame
        tf.hidden = True
        tf.delegate = self
        tf.placeholder = 'type here'
        self.add_subview(tf)
    def textfield_did_end_editing(self, textfield):
        self['label'].text = textfield.text
        textfield.hidden = True
    def onBtn(self, sender):
        self.label.text = 'calling pop'
        self['TextField'].hidden = False
        self['TextField'].bring_to_front()
        self['TextField'].begin_editing()

if __name__ == '__main__':
    w, h = ui.get_screen_size()
    v = Test((0,0,w,h))
    v.present('sheet')