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

Kivy:TabbedPanel中Popup内的ScrollView无法滚动问题

问题原因分析

这个问题的核心在于TabbedPanel默认的触摸事件拦截机制干扰了Popup内部ScrollView的触摸事件传递。TabbedPanel本身支持左右滑动切换标签页,它会监听并拦截触摸移动事件,当Popup从TabbedPanel的标签页内唤起时,ScrollView的滚动触摸事件会被TabbedPanel优先拦截,导致ScrollView无法响应滚动操作。

解决方案

我们可以通过临时禁用TabbedPanel的触摸事件处理来解决这个问题:在Popup打开时,替换TabbedPanel的触摸处理方法为不做任何操作的空方法;当Popup关闭时,恢复原有的触摸处理逻辑,这样ScrollView就能正常捕获滚动事件了。

修改后的代码示例

Python代码修改部分

from kivy.config import Config
Config.set('graphics', 'resizable', 0)
Config.set('graphics', 'position', 'custom')
Config.set('graphics', 'left', 100)
Config.set('graphics', 'top', 100)
Config.write()
from kivy.app import App
from kivy.clock import Clock
from kivy.uix.scatter import Scatter
from kivy.uix.label import Label
from kivy.uix.gridlayout import GridLayout
from kivy.uix.floatlayout import FloatLayout
from kivy.uix.textinput import TextInput
from kivy.uix.boxlayout import BoxLayout
from kivy.properties import ListProperty, ObjectProperty, BooleanProperty, StringProperty
from kivy.uix.button import Button
from kivy.uix.filechooser import FileChooser
from kivy.uix.togglebutton import ToggleButton
from kivy.uix.checkbox import CheckBox
from kivy.uix.scrollview import ScrollView
from kivy.uix.progressbar import ProgressBar
from kivy.uix.tabbedpanel import TabbedPanel
from kivy.effects.dampedscroll import DampedScrollEffect
from kivy.uix.spinner import Spinner
from kivy.core.window import Window
from kivy.lang.builder import Builder
from kivy.uix.popup import Popup

class MyWidget(TabbedPanel):
    # 假设你已经定义了spinner_choices、param_values、check_ref这些属性
    spinner_choices = []  # 示例,根据你的实际代码填充
    param_values = {}
    check_ref = {}

    def popupSettings(self, *args):
        # 保存TabbedPanel原有的触摸处理方法
        self.original_touch_down = self.on_touch_down
        self.original_touch_move = self.on_touch_move

        # 定义空的触摸处理方法,拦截后不传递给TabbedPanel的原有逻辑
        def dummy_touch_handler(*args):
            return False

        # 替换触摸处理方法
        self.on_touch_down = dummy_touch_handler
        self.on_touch_move = dummy_touch_handler

        list_of_choices = []
        list_chosen = []
        number_content = len(self.spinner_choices)
        contentF = ScrollView(do_scroll_x=False, size_hint_y=None, height=400)
        content = GridLayout(rows=number_content+1, cols=2, size_hint_y=None, height=self.minimum_height, spacing=30)
        for y in self.spinner_choices:
            content.add_widget(Label(text=y + " (Current value: {})".format(self.param_values[str(y)]), size_hint_y=None, height=30, size_hint_x=None, width=300))
            checkmate = CheckBox(size_hint_y=None, height=30)
            self.check_ref[y] = checkmate
            content.add_widget(checkmate)
        b = Button(text="OK", size_hint_y=None, height=30)
        content.add_widget(Label(text="Click here when you are done -> ", size_hint_y=None, height=30))
        content.add_widget(b)
        contentF.add_widget(content)
        p = Popup(title='Choose the parameters you want to change', content=contentF, auto_dismiss=False, size_hint_y=None, height=500, size_hint_x=None, width=500)
        b.bind(on_press=lambda *args:self.buttonValidation(p))
        p.open()

    def buttonValidation(self, p):
        # 恢复TabbedPanel原有的触摸处理方法
        self.on_touch_down = self.original_touch_down
        self.on_touch_move = self.original_touch_move
        # 这里可以添加你的确认逻辑
        p.dismiss()

class TheJamApp(App):
    def build(self):
        return MyWidget()

if __name__ == "__main__":
    Window.size=(768, 930)
    TheJamApp().run()

补充说明

  • 这种方法的优势是不需要改动KV文件,只需要修改Python逻辑即可快速解决问题。
  • 如果你希望更优雅地处理触摸事件,也可以自定义ScrollView类,强制它捕获触摸事件(比如重写on_touch_down、on_touch_move方法,确保触摸被当前ScrollView抓取),不过上面的临时禁用方法更简洁直接。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.28 04:23:01