Forum Archive

touch_began no longer called for ui.View derived class using Pythonista beta

technoway

I am running the Pythonista 3 beta.

I have a class that creates a full screen button, which I can use to covertly control something else. This is a sanitized version of the program. It's a very large program, but this smaller version demonstrates the issue I am encountering.

For the first beta, the touch_began method was called when I touched the screen, but after one of the subsequent updates, that method is no longer being called.

I am not asking for anyone to debug my program. All I want to know is should a ui.View derived class work in this case, i.e. did something break in the beta, or do I need to change to something else, perhaps a Scene?

Or, it's possible that I deleted something by mistake that made this work before?

""" testview.py
    Author: Bill Hallahan
"""
import os
import time
import speech
import ui
import motion
from ui import Image
from ui import ImageView
import types
import console
from objc_util import *

class TESTButtonView(ui.View):
    """ This user interface class forms a full-screen
        button that ... .
    """

    def __init__(self, *args, **kwargs):
        """ Initialize the user interface """
        super().__init__(*args, **kwargs)
        self.update_interval = 1.0
        # Set up an image view.
        self.width, self.height = ui.get_window_size()
        self.iv = ImageView()
        self.iv.background_color = '#000000'
        self.iv.width = self.width
        self.iv.height = self.height
        self.iv.image = Image('lock_screen.png')

    def update(self):
        """ This update function is called once a second
             to ...
        """
        # code omitted. This method is being called.
        pass

    def change_title_bar_color(self, hex_color):
        """ Change the title bar color to the passed color.
        """
        vv = ObjCInstance(self)
        bar_bckgnd = vv.superview().superview().superview().subviews()[1].subviews()[0]
        bar_bckgnd.backgroundColor = UIColor.colorWithHexString_(hex_color)

    def touch_began(self, touch):
        """ This function is called when the user
            touches the screen.
        """
        speech.say('up')

    def touch_ended(self, touch):
        """ This function is called when the user
            stops touching the screen.
        """
        speech.say('down')

def wait_for_portrait_mode():
    """ Do not return until the device is held in portrait mode. """
    msg = 'Hold your phone in portrait mode.'
    console.hud_alert(msg, duration=3)
    motion.start_updates()
    try:
        count=0
        while True:
            x, y, z = motion.get_gravity()
            count += 1
            if count > 2:
                if abs(x) < abs(y):
                    break
                else:
                    console.hud_alert(msg, duration=2)
            time.sleep(0.5)
    finally:
        motion.stop_updates()
    time.sleep(1)

if __name__ == "__main__":
    # Prevent the iPhone from going to sleep while this program runs.
    console.set_idle_timer_disabled(True)
    # Is the phone positioned correctly?
    wait_for_portrait_mode()
    # Create and display the full-screen Morse code input button.
    v = TESTButtonView()
    v.present('sheet',
              title_bar_color='#000000',
              hide_close_button=True,
              orientations=['portrait'])

Note, just to be sure there was no issue with the speech.say method being called there, I replaced that with os._exit(0). If I put that in the update method, the program exited. If I put it in the touch_began method, ran the program, and touched the screen, nothing happened.

JonB

Can you try eliminating the imageview? I think the imageview might be stealing your touches. You may need to set imageview.touch_enabled=False.

Also you may need to set touch_enabled=True on the custom view.

mikael

@technoway, one thing, that might have been introduced in some new version, is that a ui.View with no background color set will not get any touch events.

brumm

with Pythonista 3.2 +

#...
        self.iv.image = ui.Image.named('lock_screen.png')

    def draw(self):
      self.iv.image.draw()
#...

it worked for me

edit: btw. leave out the ImageView is also possible

#...
        #self.iv = ImageView()
        #self.iv...
        self.image = ui.Image.named('lock_screen.png')

    def draw(self):
      self.image.draw()
#...
technoway

brumm - Thank you. With the first change you proposed, the touch_began method is now called when I touch the screen. The image is now too large, but I'll figure that out.

JonB, than you for identifying the source of the problem. I didn't think of that.

mikael - Thank you for the response. Whatever changed, it was a while ago.

I only recently had time to work on this again. It occurs to me this also might have broken because of an IOS upgrade. I think both an IOS upgrade and a Pythonista beta update happened before I noticed it was broken.

Note, one of the things I can control is what is on the screen. In the main program, the following can be called.

    self.change_title_bar_color('000000')
    self.remove_subview(self.iv)

and in another place in the code:

    self.change_title_bar_color('334444')
    self.add_subview(self.iv)

That's why I chose an ImageView.

I have a background in digital signal processing, so I know something about images, but I have a weak understanding of Pythonista's image classes. I got things to work mostly by copying examples.

The image is now scaled way too big. I think I might need a frame? I tried setting the size a couple of ways, but that had no effect.

In any event, thanks. I will fix the image size issue - the touch_began problem had me stumped. I was looking in all the wrong places. The word "View" in "ImageView" should have given me a clue as to what was wrong.

brumm
    def draw(self):
        self.iv.image.draw(0,0,self.width,self.height)

you can only fit your image or you might like to calculate the screen ratio first...