Forum Archive

Using an ObjCInstance for touches

mr_w

Hi,

omz very helpfully shared here how to use ObjCInstance to get additional information about a touch (e.g., to distinguish between a pencil and finger touch event).

I have found that simply calling this function in touch_began, in the Examples/User Interface/Sketch.py app, causes the image_view.image to somehow be corrupted (to None) after around 18 touches.

Original code in Examples/User Interface/Sketch.py:

    def touch_began(self, touch):
        x, y = touch.location
        self.path = ui.Path()
        self.path.line_width = penwidth
        self.path.line_join_style = ui.LINE_JOIN_ROUND
        self.path.line_cap_style = ui.LINE_CAP_ROUND
        self.path.move_to(x, y)

One line addition which causes corruption:

    def touch_began(self, touch):
        # Why does this break it after around 18 strokes?
        ui_touch = ObjCInstance(touch)
        x, y = touch.location
        self.path = ui.Path()
        self.path.line_width = penwidth
        self.path.line_join_style = ui.LINE_JOIN_ROUND
        self.path.line_cap_style = ui.LINE_CAP_ROUND
        self.path.move_to(x, y)

During debugging, I found that this call seemed to be reseting sv.image_view.image to be None. (In my own code, I go on to use ui_touch to look at the pencil attributes, but that's not necessary for the test case: simply calling the function causes the problem)

Weirdly, if I save and restore the image view, it (sometimes....) seems to avoid this problem, or at least change the behaviour. Not sure what to make of that, but thought it was worth mentioning

Weird fix, maybe:

    def touch_began(self, touch):
        print(getframeinfo(currentframe()).lineno, sv.image_view.image) # Debug
        backup = sv.image_view.image
        ui_touch = ObjCInstance(touch)
        sv.image_view.image = backup
        print(getframeinfo(currentframe()).lineno, sv.image_view.image) # Debug

        x, y = touch.location
        self.path = ui.Path()
        self.path.line_width = penwidth
        self.path.line_join_style = ui.LINE_JOIN_ROUND
        self.path.line_cap_style = ui.LINE_CAP_ROUND
        self.path.move_to(x, y)

I thought this was worth reporting, and appreciate any thoughts folk have about what might be going on. Pythonista is just wonderful, by the way, thank you omz.

Mr W.

mikael

@mr_w, there is something wonky about ImageView, at least based on some the issues that I have seen here in the forums.

Without really fixing anything, here are a couple of things you could try to start with:

  • Put an on_main_thread decorator on the touch_began call
  • Use the ui4.gestures module instead of touch_began (pip install ui4 in stash)
mr_w

Thank you @mikael, that was helpful. Certainly as a workaround, then a combination of on_main_thread, my debugging print() calls, and the saving/restoring of sv.image_view.image all (when used together) seem to solve the instance of corruption. Any two of them without the third is less successful, which is all very odd: I’m guessing there’s a race condition somewhere, or that this is some kind of heisenbug.

I’ll run with this workaround for now, thank you once again for your insights and suggestions.