Kivy中collide_point()无法识别鼠标悬停问题求助
Kivy鼠标悬停控件位置偏移问题解决
问题根源
Window.mouse_pos返回的是窗口全局坐标系的坐标(原点在窗口左下角),而Widget.collide_point()方法接收的是当前控件父容器坐标系的坐标,直接传递窗口坐标会导致坐标系不匹配,出现识别位置偏移的问题。
解决方法
需要将窗口全局坐标转换为当前控件的本地坐标(或父容器坐标)后再进行碰撞检测。最简单的方式是使用to_widget()方法完成坐标转换,再传入collide_point()。
修改HoverButton类中的check_for_hover方法:
def check_for_hover(self, *args): mouse_pos = args[1] # 将窗口坐标转换为控件本地坐标 local_x, local_y = self.to_widget(*mouse_pos) if self.collide_point(local_x, local_y): print('cursor inside widget') self.text = 'cursor inside' else: print('cursor outside widget') self.text = 'cursor outside'
完整代码
Python代码
from kivy.app import App from kivy.uix.button import Button from kivy.core.window import Window from kivy.uix.floatlayout import FloatLayout class HoverButton(Button): def __init__(self, **kwargs): super(HoverButton, self).__init__(**kwargs) Window.bind(mouse_pos=self.check_for_hover) def check_for_hover(self, *args): mouse_pos = args[1] # 转换窗口坐标为控件本地坐标 local_x, local_y = self.to_widget(*mouse_pos) if self.collide_point(local_x, local_y): print('cursor inside widget') self.text = 'cursor inside' else: print('cursor outside widget') self.text = 'cursor outside' class Frame(FloatLayout): pass class HoverApp(App): def build(self): return Frame() if __name__ == '__main__': HoverApp().run()
KV语言文件
#: kivy 2.2.0 <Frame> HoverButton: pos_hint: {'x': .4, 'y': .4} size_hint: (.2, .2) text: 'cursor outside' font_size: '22sp'
补充说明
to_widget(x, y):将窗口全局坐标转换为当前控件的本地坐标,转换后的值可直接传入collide_point()完成碰撞检测。- 若需要基于父容器坐标系检测,可使用
self.to_widget(*mouse_pos, relative=True)获取父容器坐标后传入collide_point()。
内容的提问来源于stack exchange,提问作者mishaeel
相关产品推荐
相关产品推荐

