Reputation: 91
I have a Kivy app that has a scrollview within it. In this scrollview there's a boxlayout that holds a pretty big amount of images and it changes throughout runtime (it can go from 1 to 300 at any time). When a touchdown event happens, I need to know on which image the user has pressed (meaning which on they were "on" at the moment, as they can scroll up and down), and maybe even get the coordinates of the press relative to the image and not the whole screen (I need to draw on the place they pressed and I cannot do it without knowing which image they pressed on and where). How can I do that?
That's how it's defined in the kv file:
MyScrollView:
bar_color: [1, 0, 0, 1]
id: notebook_scroll
padding: 0
spacing: 0
do_scroll: (False, True) # up and down
BoxLayout:
padding: 0
spacing: 0
orientation: 'vertical'
id: notebook_image
size_hint: 1, None
height: self.minimum_height
MyImage:
<MyImage>:
source: 'images/notebook1.png'
allow_stretch: True
keep_ratio: False
size: root.get_size_for_notebook()
size_hint: None, None
It's basically an infinite notebook, and during runtime the python code adds more "MyImage" objects to the boxlayout (which is a photo of a notebook page).
Upvotes: 3
Views: 245
Reputation: 39012
Try adding this method to your MyImage
:
def to_image(self, x, y):
''''
Convert touch coordinates to pixels
:Parameters:
`x,y`: touch coordinates in parent coordinate system - as provided by on_touch_down()
:Returns: `x, y`
A value of None is returned for coordinates that are outside the Image source
'''
# get coordinates of texture in the Canvas
pos_in_canvas = self.center_x - self.norm_image_size[0] / 2., self.center_y - self.norm_image_size[1] / 2.
# calculate coordinates of the touch in relation to the texture
x1 = x - pos_in_canvas[0]
y1 = y - pos_in_canvas[1]
# convert to pixels by scaling texture_size/source_image_size
if x1 < 0 or x1 > self.norm_image_size[0]:
x2 = None
else:
x2 = self.texture_size[0] * x1/self.norm_image_size[0]
if y1 < 0 or y1 > self.norm_image_size[1]:
y2 = None
else:
y2 = self.texture_size[1] * y1/self.norm_image_size[1]
return x2, y2
Then you can add an on_touch_down()
to your MyImage
class:
def on_touch_down(self, touch):
if self.collide_point(*touch.pos):
print('got a touch on', self, 'at', touch.pos, ', at image pixels:', self.to_image(*touch.pos))
return True
else:
return super(MyImage, self).on_touch_down(touch)
Upvotes: 3