我如何在 KivyMD 中 select 目录和文件

how do I select directories and files in KivyMD

我正在尝试通过我使用 file manager 制作的一个简单应用程序 select 一个文件(图片),但我总是收到此错误消息:kivy.uix.widget.WidgetException: Cannot add <kivymd.uix.filemanager.filemanager.MDFileManager object at 0x000001D98DC5F890>, it already has a parent <kivy.uix.modalview.ModalView object at 0x000001D98DC5F4A0>,每当我点击在按钮上访问文件(即打开目录)。我不知道我想要的是错的,我什至不知道我做错了什么。

如有任何帮助,我将不胜感激。

这是我的 .py 文件

from kivy.factory import Factory
from kivy.uix.modalview import ModalView

from kivymd.uix.filemanager import MDFileManager
from kivymd.theming import ThemeManager
from kivymd.toast import toast


from kivymd.app import MDApp
from kivy.core.window import Window


Window.size = (300, 530)


class MainApp(MDApp):
    title = "File Manage"

    def __init__(self, **kwargs):
        super().__init__(**kwargs)
        Window.bind(on_keyboard=self.events)
        self.manager_open = False
        self.manager = None

    def build(self):
        self.theme_cls.primary_palette = 'Gray'
        self.theme_cls.primary_hue = '200'
        self.theme_cls.theme_style = 'Dark'

        return Factory.ExampleFileManager()

    def file_manager_open(self):
        if not self.manager:
            self.manager = ModalView(size_hint=(1, 1), auto_dismiss=False)
            self.file_manager = MDFileManager(
                exit_manager=self.exit_manager, select_path=self.select_path)
            self.manager.add_widget(self.file_manager)
            self.file_manager.show('/')  # output manager to the screen
        self.manager_open = True
        self.manager.open()

    def select_path(self, path):
        '''It will be called when you click on the file name
        or the catalog selection button.

        :type path: str;
        :param path: path to the selected directory or file;
        '''

        self.exit_manager()
        toast(path)

    def exit_manager(self, *args):
        '''Called when the user reaches the root of the directory tree.'''

        self.manager.dismiss()
        self.manager_open = False

    def events(self, instance, keyboard, keycode, text, modifiers):
        '''Called when buttons are pressed on the mobile device..'''

        if keyboard in (1001, 27):
            if self.manager_open:
                self.file_manager.back()
        return True


if __name__ == "__main__":
    app = MainApp()
    app.run()

这是我的 .kv 文件:

<ExampleFileManager@BoxLayout>
    orientation: 'vertical'

    MDToolbar:
        id: progress_toolbar
        title: 'Progress'

    ScrollView:
        MDGridLayout:
            cols: 2
            adaptive_height: True
            spacing: (10, 15)
            padding: [25, 25]

            MDLabel:
                halign: 'center'
                text: 'Before'

            MDLabel:
                halign: 'center'
                text: 'Now'

            MDCard:
                ripple_behavior: True
                orientation: 'vertical'
                size_hint_y: None
                size: 120, 220
                elevation: 15
                radius: 8
                MDIconButton:
                    icon: "camera-outline"
                    user_font_size: "64sp"
                    pos_hint: {"center_x": .5, "center_y": .5}
                    on_release: app.file_manager_open()

            MDCard:
                ripple_behavior: True
                orientation: 'vertical'
                size_hint_y: None
                size: 120, 220
                elevation: 15
                radius: 8
                MDIconButton:
                    icon: "camera-outline"
                    user_font_size: "64sp"
                    pos_hint: {"center_x": .5, "center_y": .5}
                    on_release: app.file_manager_open()


            MDTextField:
                hint_text: 'Date'
                width: 100

            MDTextField:
                hint_text: 'Date'
                width: 100

            MDTextField:
                hint_text: 'Weight'
                width: 80

            MDTextField:
                hint_text: 'Weight'
                width: 80

编辑: 新代码:

from kivy.lang import Builder
from kivymd.app import MDApp
from kivy.core.window import Window
from plyer import filechooser

Window.size = (300, 530)

KV = """
MDBoxLayout:
    orientation: 'vertical'

    MDToolbar:
        id: progress_toolbar
        title: 'Progress'

    ScrollView:
        MDGridLayout:
            cols: 2
            adaptive_height: True
            spacing: (10, 15)
            padding: [25, 25]

            MDLabel:
                halign: 'center'
                text: 'Before'

            MDLabel:
                halign: 'center'
                text: 'Now'

            MDCard:
                ripple_behavior: True
                orientation: 'vertical'
                size_hint_y: None
                size: 120, 220
                elevation: 15
                radius: 8
                MDIconButton:
                    icon: "camera-outline"
                    user_font_size: "24sp"
                    pos_hint: {"center_x": .5, "center_y": .5}
                    on_release: app.file_chooser1()
                Image:
                    id: img1
                    allow_stretch: True
                    keep_ratio: False
                    # size_hint_y: .5

            MDCard:
                ripple_behavior: True
                orientation: 'vertical'
                size_hint_y: None
                size: 120, 220
                elevation: 15
                radius: 8
                MDIconButton:
                    icon: "camera-outline"
                    user_font_size: "24sp"
                    pos_hint: {"center_x": .5, "center_y": .5}
                    on_release: app.file_chooser2()
                Image:
                    id: img2
                    allow_stretch: True
                    keep_ratio: False
                    # size_hint_y: .5


            MDTextField:
                hint_text: 'Date'
                width: 100

            MDTextField:
                hint_text: 'Date'
                width: 100

"""


class Example(MDApp):

    def build(self):
        return Builder.load_string(KV)

    def file_chooser1(self):
        filechooser.open_file(on_selection=self.selected1)

    def file_chooser2(self):
        filechooser.open_file(on_selection=self.selected2)

    def selected1(self, selection1):
        self.root.ids.img1.source = selection1[0]

    def selected2(self, selection2):
        self.root.ids.img2.source = selection2[0]


Example().run()

不使用 FileManager 小部件,实际上有一个更好的选择,它来自 plyer module,特别是 filechooser API。它的作用是打开设备的默认文件管理器应用程序以选择文件夹、文件或保存文件。这是一个例子:

def file_manager_open(self):
    from plyer import filechooser
    path = filechooser.open_file()[0] 
    # this method returns a list with the first index
    # being the path of the file selected
    toast(path)

有关此库 here 的 API 的更多信息。

我可以给你的一个提示是,因为这个文件选择器在 Windows 平台上非常弱,如果你愿意,我建议使用 tkinterfiledialog