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

Kivy FileChooserListView如何禁用文件夹展开或过滤展开内容

Kivy FileChooserListView 展开箭头过滤失效问题修复

问题核心原因:点击文件夹主体触发的open_entry是目录跳转逻辑(将目标目录设为组件当前根路径),但点击左侧小箭头触发的是TreeView自带的就地展开逻辑,不会调用重写的open_entry方法,自然不会执行路径跳转和过滤规则。

方案1:直接禁用左侧展开箭头功能

从根源避免用户触发非预期行为,通过隐藏+禁用目录项的展开按钮实现:

import os
from kivy.uix.filechooser import FileChooserListView

class CustomFileChooser(FileChooserListView):
    def __init__(self, **kwargs):
        super().__init__(**kwargs)
        self.bind(on_entry_added=self._process_dir_entry)

    def _process_dir_entry(self, _, entry, *args):
        # 仅处理目录类型的条目
        if not entry.is_dir:
            return
        # 隐藏展开箭头、禁用点击
        toggle_btn = entry.ids.toggle_button
        toggle_btn.opacity = 0
        toggle_btn.disabled = True
        toggle_btn.unbind(on_release=entry.toggle_expanded)

    # 保留原有跳转、过滤逻辑
    def open_entry(self, entry):
        maps_path = os.path.join(entry.path, "maps")
        self.filters = []
        if os.path.exists(maps_path):
            self.filters = ["*.yaml"]
            entry.path = maps_path
            return super().open_entry(entry)
        site_root = os.path.join(
            os.path.expanduser("~"), "catkin_ws", "src", "my_sites", "sites"
        )
        if entry.path != site_root:
            entry.path = site_root
        return super().open_entry(entry)

实现后用户看不到也点不了左侧展开箭头,只能通过点击文件夹主体触发预设逻辑,不会出现过滤失效。

方案2:保留展开功能,全层级应用过滤与跳转规则

如果需要保留层级展开浏览能力,不能只在open_entry中写逻辑,需要把跳转、过滤规则下沉到文件系统遍历层,确保任何场景下加载目录内容都会执行规则:

import os
from kivy.uix.filechooser import FileChooserListView, FileSystemLocal

class CustomFileSystem(FileSystemLocal):
    # 重写目录读取逻辑,自动跳转到maps子目录
    def listdir(self, path):
        maps_path = os.path.join(path, "maps")
        if os.path.isdir(maps_path):
            return super().listdir(maps_path)
        return super().listdir(path)

class CustomFileChooser(FileChooserListView):
    def __init__(self, **kwargs):
        self.file_system = CustomFileSystem()
        super().__init__(**kwargs)
        # 全局固定yaml过滤规则,无需在open_entry中反复设置
        self.filters = ["*.yaml"]
        # 固定根目录为指定sites路径
        self.bind(path=self._enforce_root_path)

    def _enforce_root_path(self, *args):
        target_root = os.path.join(
            os.path.expanduser("~"), "catkin_ws", "src", "my_sites", "sites"
        )
        if self.path != target_root and os.path.exists(target_root):
            self.unbind(path=self._enforce_root_path)
            self.path = target_root
            self.bind(path=self._enforce_root_path)

    def open_entry(self, entry):
        return super().open_entry(entry)

该实现下,无论是点击进入目录还是点箭头展开子目录,所有加载的内容都会自动执行maps子目录跳转,且仅显示yaml格式文件,不会出现漏过滤的情况。

注意事项

不要在open_entry中反复重置filters为空列表再重新赋值,全局固定过滤规则稳定性更高,也能避免切换过程中短暂显示非目标文件的闪烁问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.26 16:24:30