Kivy技术问题:如何通过坐标获取RecycleView项及分辨率适配?
场景
我有一个三列布局的窗口,第二列是包含20个项的RecycleView。当用户将文件拖放到RecycleView上时,我需要获取对应的数据源项。我仅需判断文件被拖放到了RecycleView的哪个项上,类似父级分发on_touch事件时的需求;虽然项可自行处理事件,但on_file_drop绑定在Window类上,因此必须向下查找被命中的RV项。
演示代码
<PageThumb>: size_hint: 1, None orientation: 'vertical' Image: id: imgThumbnail size_hint: 1, None height: 300 Label: id: lblPageNr size_hint: 1, None height: 20 GridLayout: cols: 3 id: mainGrid BoxLayout: size_hint: 0.4, 1 orientation: 'vertical' Label: text: '1st column' RecycleView: size_hint: 0.2, 1 id: rvMain viewclass: 'PageThumb' RecycleBoxLayout: padding: 5 spacing: 20 default_size: None, 320 default_size_hint: 1, None size_hint_y: None height: self.minimum_height orientation: 'vertical' BoxLayout: size_hint: 0.4, 1 id: layoutPreview Label: text: '3rd column'
from kivy.app import App from kivy.uix.boxlayout import BoxLayout from kivy.properties import NumericProperty class PageThumb(BoxLayout): page_nr = NumericProperty(None) def __init__(self, **kwargs): super().__init__(**kwargs) def on_page_nr(self, obj, page_nr): obj.ids.lblPageNr.text = str(page_nr+1) def on_touch_down(self, touch): if self.collide_point(*touch.pos): # touch is inside this widget app = App.get_running_app() print(f"touched page_nr={self.page_nr}") class DemoApp(App): def getSystemSizeFromScaledSize(self, win, scaledX, scaledY): scaleX = win.size[0] / win.system_size[0] scaleY = win.size[1] / win.system_size[1] systemX = scaledX * scaleX; systemY = scaledY * scaleY; return (systemX, systemY) def on_drop_file(self, win, bFileName, x, y): fileName = bFileName.decode("utf-8") xS, yS = self.getSystemSizeFromScaledSize(win, x, y) if self.root.ids.rvMain.collide_point(xS, yS): yL = self.root.ids.rvMain.layout_manager.size[1] - yS # pos = self.root.ids.rvMain.to_local(xS, yL) ndx = self.root.ids.rvMain.layout_manager.get_view_index_at(pos=(xS, yL)) page = list(self.root.ids.rvMain.layout_manager.view_indices)[ndx] print(f"d&d ndx={ndx} page_nr={page.page_nr}") def build(self): from kivy.core.window import Window Window.bind(on_drop_file = self.on_drop_file) pages = ({"page_nr": i} for i in range(0, 20)) self.root.ids.rvMain.data = pages DemoApp().run()
问题
- 如何通过
on_file_drop事件中获取的屏幕x/y坐标,从RV中找到对应的项? - 我基于分辨率密度的碰撞检测转换是否正确?目前仅在Windows平台测试,是否仅需在此平台处理?在Kivy文档中未找到相关提示。
我的分析
- 问题核心是处理
on_file_drop事件中的屏幕坐标,由于Windows桌面使用250%缩放,发现必须转换坐标才能让collide_point正确检测,类似on_touch事件的处理逻辑。 - 认为
layout_manager.get_view_index_at(pos)也需应用密度计算,但尝试RecycleView及其layout_manager的多种to_local()/to_widget()组合均未得到正确结果。 - 尝试操作
layout_manager.view_indices和children等属性也未成功。
内容的提问来源于stack exchange,提问作者andy
相关产品推荐
相关产品推荐

