Reputation: 805
I am trying to select a file (picture), through a simple app I made using file manager
, but I keep getting this error message: 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>
, whenever I click on the button to access files (i.e to open directories). I don't know want is wrong, I don't even know what I am doing wrong.
I would appreciate any help thanks.
Here's my .py file
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()
and here's my .kv file:
<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
Edit: New code:
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()
Upvotes: 2
Views: 2284
Reputation: 621
Instead of using the FileManager
widget, there is actually a better alternative which is from the plyer module, specifically the filechooser
API. What it does is to open up the default file manager app of your device to either choose folder, file or save file. Here is an example:
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)
More information regarding the APIs of this library here.
One tip I can give you is that because this file chooser is very weak on the Windows platform, I would recommend using tkinter
's filedialog
if you want.
Upvotes: 3