Search code examples
pythonkivy

Display a new screen with RecycleView


I have a first screen with a recycleview (MenuSubjects) I would like, when I click on an element of the list, display a new screen where the content of this screen depends of the button I clicked.

I can retrieve the button index, but I cannot display my new screen (MenuDetailsSubject).

I think I do something wrong, but I don't understand where. Can someone help me ?

Thanks

from kivy.app import App
from kivy.uix.button import Button
from kivy.uix.label import Label
from kivy.uix.textinput import TextInput
from kivy.uix.screenmanager import Screen
from kivy.lang import Builder 
import pandas as pd
from kivy.uix.recycleview import RecycleView
from kivy.factory import Factory

Builder.load_string("""

<RV>:
    RecycleBoxLayout:
        default_size: None, dp(56)
        default_size_hint: 1, None
        size_hint_y: None
        height: self.minimum_height
        orientation: 'vertical'
        spacing : 10

       
""")


class RVItem(Factory.Button):
    def get_data_index(self):
        return self.parent.get_view_index_at(self.center)
    def on_press(self):
        index = self.get_data_index()

        MenuDetailsSubject(index=index) #The issue is here 

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


class MenuSubjects(Screen):
    def __init__(self, **kwargs):
        if len(kwargs) >= 1:
            self.index = kwargs.pop('index')
            self.open_subject()
        super().__init__(**kwargs)

        self.title = Label(text='Title',
            font_size= '50px',
            pos_hint={'y': 0.35})

        self.new_subject_button = Button(
            text= ("Button"),
            size_hint=(0.26, 0.05),
            pos_hint={"x": 0.37, "y": 0.70},
            font_size=25,
            )

        self.layout = RV()
        self.layout.viewclass= 'RVItem'
        self.layout.size_hint = (None, None)
        self.layout.pos_hint={'x': 0.35, 'y': 0.25}
        self.layout.width= 450
        self.layout.height= 300
 

        self.quit_button = Button(
            text=("Exit"),
            font_size=20,
            size_hint=(0.1,0.05),
            pos_hint={"x": 0.10, "y": 0.10 },
            )

        self.add_widget(self.title)
        self.add_widget(self.new_subject_button)
        self.add_widget(self.layout)
        self.add_widget(self.quit_button)




class MenuDetailsSubject(Screen):
    def __init__(self, **kwargs):
        index = kwargs.pop("index")
        filename = "buttons_names.xlsx"
        data = pd.read_excel(filename)
        self.name = str(data.loc[index]["Nom"] + data.loc[index]["Prenom"])
        self.gender = str(data.loc[index]["Genre"])

        super().__init__(**kwargs)

        self.title = Label(text='Détails du sujet',
            font_size= '50px',
            pos_hint={'y': 0.35})

        self.button_previous= Button(
            text= "Précédent",
            font_size=15,
            size_hint=(0.1,0.05),
            pos_hint={"x": 0, "y": 0.9 },
            )

        self.button_supp=Button(
            text= "Supprimer",
            font_size=15,
            size_hint=(0.1,0.05),
            pos_hint={"x": 0.9, "y": 0.9 },
            )

        self.text_details=TextInput(
            text = ("Nom, prénom : " + self.name + " \n Genre : " + self.gender),
            font_size= 20,
            background_color=(0,0,0,0),
            foreground_color=(1,1,1,1),
            size_hint=(0.3,0.3),
            pos_hint={'x': 0.35, 'y': 0.4}
            )


        self.add_widget(self.title)
        self.add_widget(self.button_previous)
        self.add_widget(self.button_supp)
        self.add_widget(self.text_details)




class LaunchApp(App):
    def build(self):
        menu=MenuSubjects()
        return menu         

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

Solution

  • If you want to use Screens, you need a ScreenManager. Here is one possible approach:

    class LaunchApp(App):
        def build(self):
            sm = ScreenManager()
            sm.add_widget(MenuSubjects())
            return sm
            # menu = MenuSubjects()
            # return menu
    

    The above code creates a ScreenManager as the root widget of the App, with the MenuSubjects as one of its Screens.

    Then, in your on_press() method of RVItem:

    def on_press(self):
        index = self.get_data_index()
        App.get_running_app().root.switch_to(MenuDetailsSubject(index=index))  # The issue is here
        print(index)
    

    This code creates a new MenuDetailsSubject Screen and tells the ScreenManager to switch to it.