Python Forum
Kivy Filechooser, Saving Selection
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Kivy Filechooser, Saving Selection
#1
Hi,

I'm working on an app where (among other things)  a user can choose a folder as a working directory. i.e.  A user chooses a folder the first time he uses the app, and then the folder path will be saved within the app when he re-opens it.

I've attached code for a simplified version of the app. Overview of how it works:

1) If you click "Show Current Folder", the app will read from the file "destination.py" and pull in the text of a variable called userPath. For instance, it will say, "The current folder is C:\xyz".
2) If you choose a folder in the filechooser and then click "Change Folder", the path in destination.py (variable "userPath") will be changed to the new path. 
3) If you click "Show Current Folder" again, it should show the new path.

Problem: For #3, the popup shows the old path. In order to show the new path, I have to close and re-open the app. I've added reload(destination) statements within my code, but it doesn't seem to have any effect.

Any ideas on how I can get the "Show Current Folder" function to show the newly created path?

Thanks. I really appreciate any and all help/advice.



(Note for code below: The main code will work immediately--you just have to save the "destination.py' code in the app folder. If there is a more effective way of doing this within a single app file, I'd love to know. Apologies for any inconvenience.)

destination.py code:

userPath: ''
main.py code:

from kivy.config import Config

Config.set('graphics', 'width', '700') 
Config.set('graphics', 'height', '700')
Config.set('graphics', 'fullscreen', 'fake')

from kivy.app import App
from kivy.uix.button import Button
from kivy.core.window import Window
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.label import Label
from kivy.uix.listview import ListView
from kivy.uix.gridlayout import GridLayout
from kivy.uix.anchorlayout import AnchorLayout
from kivy.properties import ObjectProperty, StringProperty
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.lang import Builder
from kivy.core.text import LabelBase
from kivy.utils import get_color_from_hex as C
from kivy.uix.switch import Switch
from kivy.uix.checkbox import CheckBox
from kivy.uix.textinput import TextInput
from kivy.uix.popup import Popup
from os.path import join, isdir
from kivy.uix.popup import Popup
from kivy.uix.label import Label
from kivy.uix.modalview import ModalView
import destination


import pandas as pd
from pandas import *
import numpy as np
import datetime
from datetime import *
import win32com.client
import re
import os


from kivy.properties import ListProperty

# Create both screens. Please note the root.manager.current: this is how
# you can control the ScreenManager from kv. Each screen has by default a
# property manager that gives you the instance of the ScreenManager used.
Builder.load_string("""
#:import C kivy.utils.get_color_from_hex
#:import WipeTransition kivy.uix.screenmanager.WipeTransition

<DropFile>:

<RunButton>:
#color: .5,.6,.2,.7

<FileScreen>:
    MainPageGrid:
        padding:1
        spacing: 1


        MainPageButton:
            #background_color: C('#bfbf40')
            text: "Back to Menu"
            on_release: app.root.current = 'main'

        MainPageButton:
            background_color: C('#bfbf40')
            text: "Change Folder"
            on_release: root.set_folder()


        MainPageButton:
            background_color: C('#bfbf40')
            text: "Show Current Folder"
            on_release: root.popup_current() 

        BoxLayout:
            orientation: "vertical"
            FileChooserListView:
                size_hint: 1,.8
                id: filechooser
                filters: [root.is_dir]
                font_name: 'Roboto-Bold'
                rootpath: "C:\Users"
                dirselect: True
                #on_selection: my_widget.selected(filechooser.selection)
                on_selection: root.show_selection()

            TextInput:
                size_hint: 1, .1
                text: root.new_path



<MainPageGrid@GridLayout>:
    cols: 2
    spacing: 10
    row_default_height:
        (0.5* (self.width - self.spacing[0]) - self.padding[0])
    row_force_default: True
#col_default_height: 50
#(1*(self.height - self.spacing[0]) - self.padding[0])
#col_force_default: False

<MainPageButton@Button>:
    background_normal: 'button_normal.png'
    background_down: 'button_down.png'
    background_color: C('#95A5A6')
    font_size: 24
    #halign: 'center'
    markup: True

<Button>:
    background_normal: 'button_normal.png'
    background_down: 'button_down.png'
    background_color: C('#95A5A6')
    font_size: 24
    markup: True
    halign: 'center'



<PopupCurrent>:

    size_hint: .8, .4
    title: "Current Folder"
    BoxLayout:
        orientation: 'vertical'


        ScrollView:
            Label:
                id: content_text
                size_hint_y: None
                height: self.texture_size[1]
                #text: "Current folder is: " + root.msg
                text_size: (self.width-20), None
                line_height: 1.5
                valign: "top"
                text: 'Current folder is: ' + root.msg

        Button:
            text: "Proceed"
            size_hint_y: None
            height: "40dp"
            on_press: root.dismiss()



            
""")

# Declare both screens


class FileScreen(Screen):
    current_path = StringProperty()
    new_path = StringProperty()
    msg = StringProperty()
    def popup_current(self):
        reload(destination)
        PopupCurrent().open()
        
    def show_selection(self):
        sel= self.ids["filechooser"]
        try:
            self.new_path = sel.selection[0]
            print self.new_path
            return self.new_path
        except:
            pass

    def is_dir(self, directory, filename):
        return isdir(join(directory, filename))

    def set_folder(self):
        directory=self.new_path
        f= open('destination.py','w')
        p="userPath='"+ directory+"'"
        f.write(p)
        f.close()
        print p
        reload(destination)




class PopupCurrent(Popup):
    reload(destination)
    msg= StringProperty()
    msg = destination.userPath
    




class TestApp(App):
    
    def build(self):

        # Create the screen manager
        self.drops=[]
        sm = ScreenManager()

        sm.add_widget(FileScreen(name='folder'))


        Window.bind(on_dropfile=self.handledrops)
        return sm
    def handledrops(self, *args):
        
        for i in self.drops:
            i(*args)

if __name__ == '__main__':

    TestApp().run()
Reply
#2
This is looks like totally wrong approach. Configurations like this should be stored in the config file and kivy has nice interface to work with config files. All the config settings are loaded in the memory and you should work with these. If user changes configuretaion - you save to the config file, in order to be available for next time when user starts the program, but still you work with config settings that are loaded (as been changed in the meantime, i.e. in memory is always copy of the config settings as in teh file).
Even if there was no interface for config files in kivy, this should be a variable (most probably app attribute) that you work with, instead of reloading py module.
Reply
#3
Something else I should have mentioned - the module which you import will be compiled if in the future you compile your kivy app to apk (Android) or exe (Win) , so you will not be able to do what you are doing now in your code.
Reply
#4
Thanks! I looked into your suggestion and found that I could leverage Kivy's Settings/config features. Much better approach than what I was trying to do.
Reply


Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020