首页 > 解决方案 > 如何在 KivyMD 中选择目录和文件

问题描述

我正在尝试通过我使用的一个简单应用程序选择一个文件(图片),但每当我单击按钮访问文件(即打开目录)时,我都会file manager收到此错误消息: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()

标签: pythonpython-3.xkivykivy-languagekivymd

解决方案


除了使用FileManager小部件之外,实际上还有一个更好的替代方案,它来自plyer 模块,特别是 filechooserAPI。它的作用是打开设备的默认文件管理器应用程序以选择文件夹、文件或保存文件。这是一个例子:

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)

有关此库的 API 的更多信息,请点击此处

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


推荐阅读