You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Kivy中Widget类添加on_touch_down后ScrollView失效的问题解决

问题原因与解决方案

你遇到的问题核心在于Kivy的触摸事件传递机制:当你重写Widget子类的on_touch_down方法时,如果没有主动调用父类的同名方法,触摸事件就不会传递给子控件(也就是你嵌套的ScrollView),导致它无法响应触摸滚动。

你的GameManager里的on_touch_down方法只判断了触摸是否在自身范围内,但没有把事件继续传递给内部的ScrollView。Kivy中,控件的触摸事件默认会向下传递给子控件,但重写方法后这个逻辑被你覆盖了,所以ScrollView收不到触摸信号,自然没法工作。

解决方法

只需要在你的on_touch_down方法里,调用父类的on_touch_down方法,让事件继续传递下去即可。同时我也修正了原代码中ScrollViewApp类的小问题(原写法不符合Kivy App的规范),修改后的完整代码如下:

from kivy.app import App
from kivy.core.window import Window
from kivy.uix.button import Button
from kivy.uix.gridlayout import GridLayout
from kivy.uix.scrollview import ScrollView
from kivy.uix.widget import Widget

Window.size = (520, 960)

class GameManager(Widget):
    def __init__(self, **kwargs):
        super(GameManager, self).__init__(**kwargs)
        layout = GridLayout(cols=1, spacing=10, size_hint_y=None)
        layout.bind(minimum_height=layout.setter('height'))
        for i in range(100):
            btn = Button(text=str(i), size_hint_y=None, height=40)
            layout.add_widget(btn)
        root = ScrollView(size_hint=(1, None), size=(Window.width/2, Window.height*3/4))
        root.add_widget(layout)
        self.add_widget(root)
    
    def on_touch_down(self, touch):
        if self.collide_point(*touch.pos):
            # 这里可以添加你自己的触摸处理逻辑
            pass
        # 调用父类方法,让事件继续传递给子控件
        return super().on_touch_down(touch)

class ScrollViewApp(App):
    def build(self):
        return GameManager()

if __name__ == '__main__':
    ScrollViewApp().run()

补充说明

  1. 如果你需要在GameManager层做自定义触摸逻辑(比如判断触摸位置、执行特定操作),可以在if块里添加代码,然后一定要调用super().on_touch_down(touch)并返回它的结果——这样既处理了自己的逻辑,又保证子控件能收到事件。
  2. 如果你不需要在GameManager层处理触摸事件,直接删除这个on_touch_down方法即可,让Kivy默认的事件传递机制生效,这也是删除方法后恢复正常的原因。

内容的提问来源于stack exchange,提问作者Karol Borecki

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 04:41:40