0

Does anyone have any idea what could be causing this? My Kivy RecycleView has a weird static version of it behind the editable one - it can't be selected or changed in any way. This is making me think I may have a duplicate version of all of my Kivy widgets? I'm hesitant to paste all of my code as it reaches out to an api and has credential information as well as a lot of personal info in the app itself.

DoubledRecycleView


class SelectableRecycleBoxLayout(FocusBehavior, LayoutSelectionBehavior,
                                 RecycleBoxLayout):
    ''' Adds selection and focus behaviour to the view. '''


class SelectableLabel(RecycleDataViewBehavior, Label):
    ''' Add selection support to the Label '''
    index = None
    selected = BooleanProperty(False)
    selectable = BooleanProperty(True)

    def refresh_view_attrs(self, rv, index, data):
        ''' Catch and handle the view changes '''
        self.index = index
        return super(SelectableLabel, self).refresh_view_attrs(
            rv, index, data)

    def on_touch_down(self, touch):
        ''' Add selection on touch down '''
        if super(SelectableLabel, self).on_touch_down(touch):
            return True
        if self.collide_point(*touch.pos) and self.selectable:
            return self.parent.select_with_touch(self.index, touch)

    def apply_selection(self, rv, index, is_selected):
        ''' Respond to the selection of items in the view. '''
        self.selected = is_selected
        if is_selected:
            print("selection changed to {0}".format(rv.data[index]))
        else:
            print("selection removed for {0}".format(rv.data[index]))



class RV(RecycleView):

    def __init__(self, **kwargs):
        super(RV, self).__init__(**kwargs)
        self.data = [{'text': str(x)} for x in range(10)]

class GuiApp(App):
    theme_cls = ThemeManager()
    theme_cls.theme_style = 'Dark'
    previous_date = ''
    previous_date2 = ''
    StartDate = ObjectProperty("Start Date")
    EndDate = ObjectProperty("End Date")



    def build(self):
        self.pickers = Factory.AnotherScreen()
        presentation = Builder.load_file("gui.kv")
        return presentation


Here's my Kivy:


            RV:
                id: rv
                viewclass: 'SelectableLabel'
                SelectableRecycleBoxLayout:
                    default_size: None, dp(56)
                    default_size_hint: 1, None
                    size_hint_y: None
                    height: self.minimum_height
                    orientation: 'vertical'
                    multiselect: True
                    touch_multiselect: True


<SelectableLabel>:
    # Draw a background to indicate selection
    canvas.before:
        Color:
            rgba: (.4, 0.4, .4, .3) if self.selected else (.2, .2, .2, 1)
        Rectangle:
            pos: self.pos
            size: self.size

I hope this is enough information to at least give me an idea where to look..I'm also struggling to update the data in the RecycleView but that may be because of this issue? I may have two different instances of the widgets running but I'm not sure how that's possible..

eyllanesc
  • 235,170
  • 19
  • 170
  • 241
Mac
  • 5
  • 1

1 Answers1

0

Root Cause - Seeing Doubles

The double is due to loading kv file by filename convention and using Builder.

For example: Using Builder.load_file('gui.kv'), and your kv filename is gui.kv.

Snippets

class GuiApp(App):
    ...

    def build(self):
        self.pickers = Factory.AnotherScreen()
        presentation = Builder.load_file("gui.kv")
        return presentation

Solution

There are two solutions to the problem.

Method 1

Rename the App class from GuiApp() to TestApp()

Method 2

There is no need to return anything in App class as long as there is root rule e.g. BoxLayout: in the kv file.

Remove the following:

  • presentation = Builder.load_file("gui.kv")
  • return presentation

References

Kv language » How to load KV

There are two ways to load Kv code into your application:

By name convention:

Kivy looks for a Kv file with the same name as your App class in lowercase, minus “App” if it ends with ‘App’ e.g:

MyApp -> my.kv

If this file defines a Root Widget it will be attached to the App’s root attribute and used as the base of the application widget tree.

By Builder convention:

You can tell Kivy to directly load a string or a file. If this string or file defines a root widget, it will be returned by the method:

Builder.load_file('path/to/file.kv')

or:

Builder.load_string(kv_string)

Example

main.py

from kivy.app import App


class GuiApp(App):

    def build(self):
        self.pickers = None


if __name__ == "__main__":
    GuiApp().run()

gui.kv

#:kivy 1.11.0

Button:
    text: 'Hello Kivy'
    font_size: 50

Output

Result

ikolim
  • 15,721
  • 2
  • 19
  • 29
  • I thought in order for the kv file to be automatically opened without the need to use the Builder it had to be the same name as your main py file or something? My py file name is "HarvestIntel.py" with my kv file named "gui.kv". So are you saying I can remove the Builder line in my build method? What would I return then in order to load the kivy file? Thanks for the help! – Mac Apr 05 '19 at 18:12
  • Since your App class is `GuiApp`, Kivy looks for a Kv file with the same name as your App class in lowercase, minus “App” i.e. `gui.kv`. That's correct, you can remove the `presentation = Builder.load_file('gui.kv')` – ikolim Apr 05 '19 at 18:28
  • I have updated the post with solution and reference to Kivy documentation. Please remember to accept and/or up-vote the answer. Thank you. – ikolim Apr 05 '19 at 18:53
  • Thank you so much for your help that worked perfectly! With how my code is layed out with my separate RV(RecycleView) class where do I put the code to update the data? Like I want a data to completely update everything. Do I put it in my RV class? Because every time I call that class my init will run and wipe out the data? Does that make sense? I also don't know how to call that from kivy on button press? – Mac Apr 06 '19 at 00:22
  • When Kivy processed the kv file, the class RV was instantiated by kv language, `RV:`. In Python script, reference/call the instantiated class RV by its `id` i.e. `rv` as declared in kv file e.g. `self.root.ids.rv.attribute-name` or `self.root.ids.rv.method-name`. You might want to check another post using RecycleView, [How to add vertical scroll to RecycleView](https://stackoverflow.com/questions/50219281/python-how-to-add-vertical-scroll-in-recycleview/50299444#50299444) . – ikolim Apr 06 '19 at 14:20