Search code examples
pythonkivyfilechooser

Kivy FileChooser Overlapping


I am using the FileChooserListView from kivy and have run into a overlapping text on scroll with screens that another user came across as well. I looked through their post on GitHub and read that some people are using the plyer FileChooser. I also saw that someone mentioned that it has to do with the Building function of the .kv file. I created a new kivy app and the problem did not occur, but when I return to my older app (no changes of any kind) the problem still occurs.

Sorry for the long post, but I am unsure how these two kivy app codes are different. Am I calling something twice that is causing the FileChooser to "hold" it's position? I am not oppose to using plyer's FileChooser, but could someone give me an example on how to implement it?

testing_kivy.py

from kivy.app import App
from kivy.lang.builder import Builder
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.uix.popup import Popup
from kivy.properties import ObjectProperty
from kivy.uix.floatlayout import FloatLayout
import os


def train_load(path, filename):
    download_path = os.path.join(path, filename[0])
    print(download_path)


class LoadDialog(FloatLayout):
    load = ObjectProperty(None)
    cancel = ObjectProperty(None)


class TrainingWindow(Screen):
    def show_load_list(self):
        content = LoadDialog(load=train_load, cancel=self.dismiss_popup)
        self._popup = Popup(title="Load a file list", content=content, size_hint=(1, 1))
        self._popup.open()

    def dismiss_popup(self):
        self._popup.dismiss()


class WindowManager(ScreenManager):
    pass


kv_training = Builder.load_file('testing_kivy.kv')


class MyApp(App):
    def build(self):
        return kv_training


if __name__ == '__main__':
    MyApp().run()

testing_kivy.kv

WindowManager:
    TrainingWindow:


<TrainingWindow>
    name: "training"

    BoxLayout:
        orientation: "vertical"
        Button:
            text: "Select Training Images"
            font_size: 32
            on_release: root.show_load_list()
        Button:
            text: "Select Training Annots"
            font_size: 32
            on_release: root.show_load_list()

        Button:
            text: "Set Parameters"
            font_size: 32
            on_release:
                app.root.current = "parameters_train"
                root.manager.transition.direction = "up"

        Button:
            text: "Back"
            font_size: 16
            on_release:
                app.root.current = "select"
                root.manager.transition.direction = "right"


<LoadDialog>:
    BoxLayout:
        size: root.size
        pos: root.pos
        orientation: "vertical"
        FileChooserListView:
            id: filechooser
        BoxLayout:
            size_hint_y: None
            height: 30
            Button:
                text: "Cancel"
                on_release: root.cancel()
            Button:
                text: "Load"
                on_release: root.load(filechooser.path, filechooser.selection)

enter image description here

Older_app.py

from kivy.app import App
from kivy.lang.builder import Builder
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.uix.popup import Popup
from kivy.uix.button import Button
from kivy.uix.boxlayout import BoxLayout
from kivy.properties import ObjectProperty
from kivy.uix.floatlayout import FloatLayout
from kivy.uix.spinner import SpinnerOption
import os
import pandas as pd


def invalid_login():
    app = App.get_running_app()
    app.root.current = "main"
    # Create a BoxLayout to add multiple lines or buttons to a PopUp
    box = BoxLayout()
    # Create PopUp
    pop = Popup(
        title="Invalid Password",
        size_hint=(None, None), size=(200, 100),
        content=box,
        auto_dismiss=False
    )
    # Dismiss PopUp
    box.add_widget(Button(text="Close", on_release=pop.dismiss))
    pop.open()


def model_load(path, filename):
    download_path = os.path.join(path, filename[0])
    print(download_path)


def train_load(path, filename):
    download_path = os.path.join(path, filename[0])
    print(download_path)


def train_model_load(path, filename):
    download_path = os.path.join(path, filename[0])
    print(download_path)


class MainWindow(Screen):
    def login(self):
        if self.ids.password.text == "password":
            self.ids.password.text = ""
            app = App.get_running_app()
            app.root.current = "select"
        else:
            self.ids.password.text = ""
            invalid_login()


class SelectWindow(Screen):
    pass


class LoadDialog(FloatLayout):
    load = ObjectProperty(None)
    cancel = ObjectProperty(None)


class TrainingWindow(Screen):
    def show_load_list(self):
        content = LoadDialog(load=train_load, cancel=self.dismiss_popup)
        self._popup = Popup(title="Load a file list", content=content, size_hint=(1, 1))
        self._popup.open()

    def dismiss_popup(self):
        self._popup.dismiss()


class ModelWindow(Screen):
    def show_load_list(self):
        content = LoadDialog(load=model_load, cancel=self.dismiss_popup)
        self._popup = Popup(title="Load a file list", content=content, size_hint=(1, 1))
        self._popup.open()

    def dismiss_popup(self):
        self._popup.dismiss()


class TrainModelWindow(Screen):
    def show_load_list(self):
        content = LoadDialog(load=train_model_load, cancel=self.dismiss_popup)
        self._popup = Popup(title="Load a file list", content=content, size_hint=(1, 1))
        self._popup.open()

    def dismiss_popup(self):
        self._popup.dismiss()


class ParametersTrainModelWindow(Screen):
    pass


class ParametersTrainWindow(Screen):
    pass


class WindowManager(ScreenManager):
    pass


class OverViewTrainWindow(Screen):
    pass


class OverViewTrainModelWindow(Screen):
    pass


class OverViewModelWindow(Screen):
    pass


class MyOption(SpinnerOption):
    pass


kv_main= Builder.load_file('main.kv')


class MyApp(App):
    def build(self):
        return kv_main


if __name__ == '__main__':
    MyApp().run()

main.kv

#:import utils kivy.utils
#:include select.kv
#:include training.kv
#:include model.kv
#:include train_model.kv
#:include parameters_train.kv
#:include parameters_train_model.kv
#:include overview_train_model.kv
#:include overview_train.kv
#:include overview_model.kv

WindowManager:
    MainWindow:
    SelectWindow:
    TrainingWindow:
    ModelWindow:
    TrainModelWindow:
    ParametersTrainWindow:
    ParametersTrainModelWindow
    OverViewTrainWindow:
    OverViewTrainModelWindow:
    OverViewModelWindow:

<MainWindow>
    name: "main"

    GridLayout:
        cols: 1

        BoxLayout:
            orientation: "vertical"
            canvas.before:
                Color:
                    rgba: 0,0,0,1
                Rectangle:
                    pos: self.pos
                    size: self.size
            Label:
                size_hint: 1, 1
                text: "SPECPHASE"
                font_size: 50
                color:
                    utils.get_color_from_hex('#FF0000')
            Label:
                size_hint: 1, 1
                text: "Object Detection App"
                font_size: 40

        BoxLayout:
            size_hint: 1, 0.005
            canvas.before:
                Color:
                    rgba: (1,1,1,1)
                Rectangle:
                    size: self.size
                    pos: self.pos

        BoxLayout:
            orientation: "horizontal"
            size_hint: (0.35, 0.35)
            padding: (0,0,25,0)

            Label:
                font_size: 20
                text: "Password"
                size_hint: (0.5, 0.35)
                pos_hint: {'x': 1, 'y': 0.4}
                background_color: (0,0,0,1)
                canvas.before:
                    Color:
                        rgba: self.background_color
                    Rectangle:
                        size: self.size
                        pos: self.pos


            TextInput:
                id: password
                multiline: False
                size_hint: (0.5, 0.35)
                pos_hint: {'x': 1, 'y': 0.4}
                focus: True
                background_color:
                    utils.get_color_from_hex('#18B8D9')
                cursor_color: (0,0,0,1)
                password: True


        Button:
            text: "Submit"
            on_release: root.login()

select.kv

<SelectWindow@Screen>:
    name: "select"

    GridLayout:
        cols: 1

        GridLayout:
            cols: 2

            Button:
                text: "Train"
                font_size: 32
                on_release:
                    app.root.current = "training"
                    root.manager.transition.direction = "right"
            Button:
                text: "Model"
                font_size: 32
                on_release:
                    app.root.current = "model"
                    root.manager.transition.direction = "left"

        Button:
            text: "Train & Model"
            font_size: 32
            on_release:
                app.root.current = "train_model"
                root.manager.transition.direction = "up"

training.kv

<TrainingWindow@Screen>:
    name: "training"

    BoxLayout:
        orientation: "vertical"
        Button:
            text: "Select Training Images"
            font_size: 32
            on_release: root.show_load_list()
        Button:
            text: "Select Training Annots"
            font_size: 32
            on_release: root.show_load_list()

        Button:
            text: "Set Parameters"
            font_size: 32
            on_release:
                app.root.current = "parameters_train"
                root.manager.transition.direction = "up"

        Button:
            text: "Back"
            font_size: 16
            on_release:
                app.root.current = "select"
                root.manager.transition.direction = "right"


<LoadDialog>:
    BoxLayout:
        size: root.size
        pos: root.pos
        orientation: "vertical"
        FileChooserListView:
            id: filechooser
        BoxLayout:
            size_hint_y: None
            height: 30
            Button:
                text: "Cancel"
                on_release: root.cancel()
            Button:
                text: "Load"
                on_release: root.load(filechooser.path, filechooser.selection)

enter image description here


Solution

  • After taking a break from this for while and restarting my brain, I was able to find the problem.

    Not included in my question, I have a couple more .kv files that have a similar layout to the training.kv. They are used to access other screens. I found that I was calling FileChooserListView in each screen and I belive that is why I was seeing the stacking problem. I ended up removing all of them except for the one in my training.kv file and all is working.