0

I'm new to Kivy and I stumbled upon an issue when using the RecycleViw. Basically, I have a switch for every entry in my recycle view to activate or deactivate the text input. This said, when I activate the "profilename_1", it also activates the "profilename_7" (see images below).

Example when OFF: profilename_1 profilename_7

Example when ON: profilename_1 profilename_7

If I enable the "profilename_2" it will also enable "profilename_8" and so on. How can I make each entry its own individual element/object, where it's completely independent of one another?

Here's my code:

PYTHON MAIN FILE:

from kivy.app import App
from kivy.uix.widget import Widget
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.floatlayout import FloatLayout
from kivy.properties import ObjectProperty, StringProperty, NumericProperty
from models import Profile
import json

class ProfileWidget(BoxLayout):
    profilename = StringProperty()
    phonenumber = NumericProperty()
    alias = StringProperty()

class MainWidget(FloatLayout):
    recycleView = ObjectProperty(None)
    def __init__(self, **kwargs):
        super().__init__(**kwargs)
        self.profiles = fetch_profiles()

    def on_parent(self, widget, parent):
        self.recycleView.data = [profile.get_dictionary() for profile in self.profiles]

def fetch_profiles():
    file = open("data.json")
    result = json.load(file)
    profile_list = []

    for x in result['profiles']:
        profile = Profile(x["profilename"], x["phonenumber"], x["alias"])
        profile_list.append(profile)
    
    return profile_list

class SwitchTestApp(App):
    pass

SwitchTestApp().run()

MODELS.PY FILE (UPDATE)

class Profile:
    profilename = ""
    phonenumber = 0
    alias = ""

    def __init__(self, profilename, phonenumber, alias):
        self.profilename = profilename
        self.phonenumber = phonenumber
        self.alias = alias

    def get_dictionary(self):
        return {"profilename": self.profilename, "phonenumber": self.phonenumber, "alias": self.alias}

KIVY FILE (named SwitchTest.kv in this case):

#:import utils kivy.utils
#:set color1 "#DD7835"

MainWidget:

<MainWidget>:
    recycleView: recycleView
    BoxLayout:
        orientation: "vertical"
        FitLabel:
            text: "PROFILES LIST"
            color: 1, 1, 1, 1
            font_size: dp(22)
            canvas.before:
                Color:
                    rgb: utils.get_color_from_hex(color1)
                Rectangle:
                    pos: self.pos
                    size: self.size

        BoxLayout:
            padding: dp(100), dp(20)
            RecycleView:
                id: recycleView
                viewclass: "ProfileWidget"
                RecycleBoxLayout:
                    default_size: None, dp(115)
                    default_size_hint: 1, None
                    size_hint_y: None
                    height: self.minimum_height
                    orientation: 'vertical'
                    spacing: dp(16)

<ProfileWidget>:
    BoxLayout:
        orientation: "vertical"
        Label:
            text: root.profilename
            color: 1, 1, 1, 1
            bold: True
            font_size: dp(22)
            text_size: self.size
            halign: "left"
            valign: "center"
        BoxLayout:
            FmtLabel:
                text: "Profile Name: "
            TextInput:
                text: str(root.profilename).upper()
                disabled: not switchID.active
                on_text_validate: root.on_text_validate(self)
        BoxLayout:
            FmtLabel:
                text: "Phone Number: "
            TextInput:
                text: str(int(root.phonenumber))
                disabled: not switchID.active
        BoxLayout:
            FmtLabel:
                text: "Alias: "
            TextInput:
                text: str(root.alias)
                disabled: not switchID.active

    BoxLayout:
        orientation: "vertical"
        padding: dp(20), dp(15)
        Switch:
            id: switchID
            size_hint: None, 1
            width: "100dp"
            active: False
            # on_active: root.switch_click(self, self.active)
        Button:
            text: "SAVE"
            size_hint: None, None
            width: "100dp"
            height: "25dp"
            opacity: 0 if not switchID.active else 1
            bold: True
            background_color: 0,1,0,1
            disabled: not switchID.active
        BoxLayout:
            size_hint_y: 0.8

<FmtLabel@Label>:
    color: 1, 1, 1, 1
    text_size: self.size
    halign: "left"
    valign: "center"

<FitLabel@Label>:
    color: 1, 0, 0, 1
    size_hint: None, None
    size: self.texture_size

I've tried assigning IDs to each element and playing with that, but no success either.

Also, this is my first post on StackOverflow, if I didn't do it right, please let me know! :)

Thank you!

RitaFuchs
  • 1
  • 2
  • The main issue is that `RecycleView` recycles your `ProfileWidget` instances. Without action by you, the `Switch` in the `ProfileWidget` will not have any logical setting. The key is to include the `Switch` setting in your `RecycleView` data and update that data as needed. This is just a hint, it can get very complicated. – John Anderson Nov 19 '22 at 14:01
  • Thank you, I will try to check that more in-depth. Except for including the Switch in the recycleview I'm not sure how to include it in the data, but I'll try and post the solution if it works. – RitaFuchs Nov 22 '22 at 15:18
  • You don't want to include the `Switch` in the RecycleView, it is already there as it is a child of your `ProfileWidget`. To add it to the data, add a `BooleanProperty` to your `ProfileWidget` to contain the `Switch` state, and in your `kv` use that `BooleanProperty` as the `active` state of the `Switch`. Then include the name of that `BooleanProperty` in the data dictionary. – John Anderson Nov 23 '22 at 16:37
  • So, in the **main.py** file: I've added the `BooleanProperty` to the `ProfileWidget` as follow: `switch_state = BooleanProperty()` Then in my `fetch_profile()` function I've set the default to False for every data entry. In the `SwitchTestApp.kv` file, I changed the 'active' state to `root.switch_state`, but the problem is still there. – RitaFuchs Nov 23 '22 at 21:36

0 Answers0