omz:forum

    • Register
    • Login
    • Search
    • Recent
    • Popular

    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.


    Polling from a ui.View (built in timers in ui.Views)

    Pythonista
    timer ui.view
    6
    40
    25245
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • Phuket2
      Phuket2 @enceladus last edited by

      This post is deleted!
      1 Reply Last reply Reply Quote 0
      • Phuket2
        Phuket2 @enceladus last edited by

        @enceladus , they thanks for your code samples also.

        I modified your update method in the first example. Just quickly, so it would stop after closing the window. Guessing more checks should be done.

        def update(self, event_loop):
                if not self.on_screen:
                    event_loop.stop()
                    return
                    
                self.set_needs_display()
                event_loop.call_later(.5, self.update, event_loop)
        

        According to the docs the BaseEventLoop class is not thread safe. I am not good enough to under the implications/restrictions of this both as a standalone as well how it would interact with Pythonista's Threads. Any insights would be appreciated.
        Again, for me at least is just to have a reliable and controllable way to easily add a way to call a so called poll/update method on a class, including a ui.View async.

        Out of the above implementations again I am not good enough to say which is the best implementation. Appears asyncio is py3+ only. Which is fine by me, other might be looking for a 2.7 solution also.

        1 Reply Last reply Reply Quote 0
        • enceladus
          enceladus last edited by

          I think that calls in event loop are run on the same thread. Button action (in stop watch example) should be put in the same event loop so that there are no thread-safety issues. As you have mentioned there could be other issues. (My experience in asyncio module is very limited and I am in learning mode.)

          def button_action(sender):
              event_loop.call_soon(button_action_event_loop, sender)
              
          def button_action_event_loop(sender):
              v1 = sender.superview['view1']    
              if sender.title == 'Reset':
                  v1.value = 0
                  v1.state = 'stop'
              elif sender.title == 'Start':
                  v1.value = 0
                  v1.state = 'run'
              elif sender.title == 'Stop':
                  v1.state = 'stop'
          
          
          1 Reply Last reply Reply Quote 0
          • omz
            omz last edited by

            @Phuket2 I've added something to the latest beta. From the release notes:

            In custom ui.View subclasses, you can now implement an update method (no arguments, except for self) that gets called automatically by an internal timer. To make this work, you also have to set the new update_interval attribute. It specifies how often the timer fires (e.g. set to 1.0, the timer fires every second). It defaults to 0.0 (disable update timer) because otherwise this new feature might break existing code that happens to implement a method called update.

            I hope this works for you.

            Phuket2 1 Reply Last reply Reply Quote 2
            • Phuket2
              Phuket2 @omz last edited by

              @omz , yup pulled another rabbit out of the hat :) was so excited when I seen the email this morning for the new beta. You have seemed to have done a lot. Just did a quick test with the update method. Appears to work perfectly. Just had a button on a form to start and stop the updates by setting the update interval. Very nice. I will do some more tests with opening Dialogs over the top etc... but many thanks, I think this will make a lot of ppl happy. Ok, back to exploring the new features :)

              1 Reply Last reply Reply Quote 0
              • technoway
                technoway last edited by

                Is the update_interval, and update, attributes in the latest pythonista?
                If now, can I get the beta?

                By the way, it would be nice if the update method was an empty method (just "pass") that already existed, so users could set the update_interval and update method in the subclassed view's init method.

                And whatever already exists, or is done in the future, thank you for a truly great product!

                1 Reply Last reply Reply Quote 0
                • omz
                  omz last edited by omz

                  @technoway It's currently only in the beta. With regards to an empty method in the base class, setting the method in __init__ etc., that's not really possible because the act of implementing the method is a signal to change the behavior (hope that makes sense). The entire update timer machinery isn't initialized at all if your View class doesn't implement update.

                  mikael 1 Reply Last reply Reply Quote 0
                  • technoway
                    technoway last edited by

                    Thank you for the quick reply.

                    Am I allowed to install the beta version, and if so, where is it?

                    I am running Pythonista on an iPhone (and iPad too, but I need this particular functionality on my iPhone).

                    I have purchased both the Python 2.x and the Python 3.x versions of Pythonista for my iPhone.

                    1 Reply Last reply Reply Quote 0
                    • technoway
                      technoway last edited by

                      Ah, I found the message about sending my apple ID through the e-mail. I'll do that. Thanks again, and sorry for all the noise. (I did search before my last post, but missed the relevant post).

                      1 Reply Last reply Reply Quote 0
                      • omz
                        omz last edited by

                        @technoway You should have a beta invite in your email (please check your spam folder if it isn't there).

                        mikael 1 Reply Last reply Reply Quote 0
                        • mikael
                          mikael @omz last edited by

                          @omz, arrgh, spam. I have been patiently waiting for my invite, so long that the spam folder has been purged already. Is it easy for you to resend my invite, or should I just send another request? Sorry.

                          1 Reply Last reply Reply Quote 0
                          • omz
                            omz last edited by

                            @technoway I sent the invite to the Gmail address you sent me yesterday. Did you just purge your spam folder?

                            mikael 1 Reply Last reply Reply Quote 0
                            • mikael
                              mikael @omz last edited by

                              @omz, I am not technoway. Sorry for jumping in; I have been waiting for the beta invite in order to test the polling functionality.

                              1 Reply Last reply Reply Quote 0
                              • omz
                                omz last edited by

                                @mikael Ah, I'm sorry, I'll send a new invite to the email address you're using for this forum.

                                mikael 1 Reply Last reply Reply Quote 1
                                • mikael
                                  mikael @omz last edited by

                                  @omz, got it, thanks!

                                  1 Reply Last reply Reply Quote 0
                                  • mikael
                                    mikael @omz last edited by

                                    @omz, some feedback on the update feature, all of it positive:

                                    • Very stable and consistent. Stops when the view is closed, no threading hassles.
                                    • Very intuitive to use. Changing the update_interval to 0.0 stops updates, and positive numbers start them again.

                                    With my limited Threading skills, I was unable to create stable and predictable UI animations with either ui.delay or custom Threads. With update, no issues. This is my vote for moving the feature out of beta.

                                    1 Reply Last reply Reply Quote 2
                                    • omz
                                      omz last edited by

                                      @mikael Thanks for your feedback! I appreciate it.

                                      technoway 1 Reply Last reply Reply Quote 0
                                      • mikael
                                        mikael @Phuket2 last edited by

                                        @Phuket2, thank you for taking this up.

                                        Phuket2 2 Replies Last reply Reply Quote 0
                                        • Phuket2
                                          Phuket2 @mikael last edited by

                                          @mikael , thanks all to @omz. When i had to do something threaded or in a loop, I never felt confident about it. I have a small thing now where its just a label update to show when something expires. It's so nice and simple with update mechanism.
                                          My experience has been same as yours. Very stable.

                                          1 Reply Last reply Reply Quote 0
                                          • Phuket2
                                            Phuket2 @mikael last edited by Phuket2

                                            @mikael , I mentioned something in the github issues area about ui.TableViewCell. @omz said just add your view to the cell. I had forgotten @JonB had helped me with this a long time ago. Anyway, i was playing around. The below maybe is not pretty. But I find it interesting and it shows off a few things. Also how well update works. Well i think it does anyway.

                                            EDIT: to see the cool stuff I think you have to tap a cell and also scroll. You can see how things are getting suspended when you scroll. I think its nice

                                            import ui
                                            from random import choice
                                            
                                            
                                            _color_list = ['purple', 'orange', 'deeppink', 'lightblue', 'cornflowerblue'
                                                           'red', 'yellow', 'green', 'pink', 'navy', 'teal', 'olive',
                                                           'lime', 'maroon', 'aqua', 'silver', 'fuchsia',
                                                           ]
                                            
                                            
                                            class MyCustomCell(ui.View):
                                                def __init__(self, parent, *args, **kwargs):
                                                    super().__init__(*args, **kwargs)
                                                    self.cell = parent
                                                    self.tableview = None
                                                    self.blink_count = 0
                                                    self.lb = None
                                                    self.frame = self.cell.frame
                                                    self.flex = 'wh'
                                                    self.width -= 10
                                                    self.x = 5
                                                    self.height -= 10
                                                    self.y = 5
                                                    self.alpha = .5
                                                    self.corner_radius = 6
                                            
                                                    # this allows the touch events to pass through my subview
                                                    self.touch_enabled = False
                                            
                                                    self.update_interval = .2
                                            
                                                    lb = ui.Label(frame=(0, 0, 24, 24), bg_color='black',
                                                                  text_color='white', alignment=ui.ALIGN_CENTER)
                                            
                                                    lb.center = self.center
                                                    lb.corner_radius = 12
                                            
                                                    self.lb = lb
                                                    self.add_subview(lb)
                                            
                                                def rect_onscreen(self):
                                                    '''
                                                    Have to write this method.  Would be nice if this was built in.
                                                    like ui.TableView.is_visible for example.  I know its just some rect
                                                    math, but it means you need to save extra references etc.. to calculate
                                                    it yourself.
                                                    '''
                                                    return True
                                            
                                                def update(self):
                                                    if not self.tableview:
                                                        return
                                            
                                                    # I did not implement this yet. A little drunk and having a party today.
                                                    # but gives the idea...
                                                    if not self.rect_onscreen():
                                                        return
                                            
                                                    if self.blink_count == 98:
                                                        self.update_interval = 0
                                            
                                                    self.blink_count += 1
                                                    self.lb.text = str(self.blink_count)
                                                    self.bg_color = choice(_color_list)
                                            
                                            
                                            def create_cell():
                                                '''
                                                Create and return a ui.TableViewCell. We add a custom ui.View to
                                                the TableViewCell.content_view. This means our view is sitting on top
                                                of the normal TableViewCell contents. All is still there.
                                                Also create an attr in the cell at runtime that points to our custom class.
                                                I guess this can be done many ways.  I choose this way for the example.
                                                To me its at least clear for access.
                                                '''
                                                cell = ui.TableViewCell()
                                                myc = MyCustomCell(cell)
                                                cell.content_view.add_subview(myc)
                                                cell.my_cell = myc
                                                return cell
                                            
                                            
                                            class MyDataSource(object):
                                            
                                                def __init__(self, data):
                                                    self.data = data
                                                    self.sel_item = 0
                                                    self.cells = [create_cell()
                                                                  for _ in range(len(self.data))]
                                            
                                                def tableview_number_of_rows(self, tableview, section):
                                                    # Return the number of rows in the section
                                                    return len(self.data)
                                            
                                                def tableview_cell_for_row(self, tableview, section, row):
                                                    # Create and return a cell for the given section/row
                                                    cell = self.cells[row]
                                                    cell.text_label.text = self.data[row]
                                            
                                                    # just showing we can access our class from the my_cell attr
                                                    # we added. In this case I want to save the tableview attr
                                                    cell.my_cell.tableview = tableview
                                                    return cell
                                            
                                                def tableview_did_select(self, tableview, section, row):
                                                    # Called when a row was selected.
                                                    self.select_row(row)
                                            
                                                def select_row(self, sel_row):
                                                    for cell in self.cells:
                                                        cell.accessory_type = ""
                                            
                                                    self.cells[sel_row].accessory_type = 'checkmark'
                                                    self.sel_item = sel_row
                                            
                                            
                                            def get_table(items):
                                                tbl = ui.TableView(frame=(0, 0, 300, 400))
                                                tbl.data_source = MyDataSource(items)
                                                tbl.delegate = tbl.data_source
                                                return tbl
                                            
                                            
                                            if __name__ == '__main__':
                                                v = get_table(['Ian', 'Fred', 'John', 'Paul', 'Gaew', 'Pete',
                                                               'Ole', 'Christian', 'Mary', 'Susan', 'Juile'
                                                               'Simone', 'Terry', 'Michael', 'James'])
                                                v.present(style='sheet', animated=False)
                                            
                                            mikael 1 Reply Last reply Reply Quote 0
                                            • First post
                                              Last post
                                            Powered by NodeBB Forums | Contributors