Can't switch to another screen from custom widget with values

24 views
Skip to first unread message

Han Met

unread,
Apr 15, 2024, 6:01:40 AMApr 15
to Kivy users support
I am new in kivy,

my app consists of  main.py, views/page1, views/page2, views/page3, widget/rowdata

my problem is :
rowdata [custom widget] loaded into page1 with data[id, name, phone] and two buttons [info, show file]

i want when i press on info button goto page3 with current values of rowdata [id, name, phone],  And when i press on show file button goto page2 with current values [id, name, phone]
how can i do it:
-------------------------------------

# main.py

from kivy.app import App
from kivy.lang import Builder
from kivy.uix.screenmanager import ScreenManager
from views.page1 import Page1
from views.page2 import Page2
from views.page3 import Page3

KV='''
PageManager:
    id: pm
    Page1Screen:
        name: 'p1'
    Page2Screen:
        name: 'p2'
    Page3Screen:
        name: 'p3'
'''
class Page1Screen(Page1):
    pass
class Page2Screen(Page2):
    pass
class Page3Screen(Page3):
    pass
class PageManager(ScreenManager):
    pass

class TestApp(App):
    def build(self):
        return Builder.load_string(KV)
   
if __name__=='__main__':
    TestApp().run()

----------------------------------------------

# views/page1.py

from kivy.uix.screenmanager import Screen
from kivy.lang import Builder
from widget.rowdata import RowData
from kivy.properties import StringProperty

Builder.load_string(
'''
<Page1>:
    BoxLayout:
        orientation: 'vertical'
        Label:
            text: 'Page1 Screen'
            halign: 'center'
            size_hint_y: None
            height: 50
        Button:
            text: 'load'
            pos_hint: {'center_x': .5, 'center_y': .5}
            size_hint: .7, .1
            on_release:
                root.lod_data()

        ScrollView:
            do_scroll: False, True
            GridLayout:
                id: grid
                cols: 1
                size_hint_y: None
                height: 1000
'''
)

class RD(RowData):
    text1 = StringProperty('')
    text2 = StringProperty('')
    text3 = StringProperty('')

class Page1(Screen):
    def __init__(self, **kw):
        super().__init__(**kw)

    def lod_data(self):
        my_lst = [
            {'name': 'Mohamed Ahmed',
             'id': '0001',
             'phone':'0100010001'},

            {'name': 'Sayed Abbas',
             'id': '0002',
             'phone':'0100010002'},

            {'name': 'Abd El-Hamid Shawky',
            'id': '0003',
            'phone':'0100010003'},
        ]
        for lst in my_lst:
            rd1= RD(text1=lst['name'], text2=lst['id'], text3=lst['phone'],)            
            self.ids.grid.add_widget(rd1)

--------------------------------------------------

# views/page2.py

from kivy.uix.screenmanager import Screen
from kivy.lang import Builder

Builder.load_string(
'''
<Page2>:
    BoxLayout:
        orientation: 'vertical'            
        Label:
            text: 'Page2 Screen'
            halign: 'center'
       
        Label:
            id: lb_name
        Label:
            id: lb_id
        Label:
            id: lb_phone
'''
)
class Page2(Screen):
    pass

-----------------------------------------------------------

# views/page3.py

from kivy.uix.screenmanager import Screen
from kivy.lang import Builder

Builder.load_string(
'''
<Page3>:
    BoxLayout:
        orientation: 'vertical'            
        Label:
            text: 'Page3 Screen'
            halign: 'center'
       
        Label:
            id: lb_name
        Label:
            id: lb_id
        Label:
            id: lb_phone
'''
)
class Page3(Screen):
    pass

---------------------------------------------------------

# widget/rowdata

from kivy.uix.gridlayout import GridLayout
from kivy.lang import Builder

Builder.load_string(
'''
<RowData>:
    cols: 3
    size_hint_y: None
    height: 75
    size_hint_x: .8
    spacing: dp(10)
    padding: dp(10)

    Button:
        text: 'info.'
        size_hint_x: .1
    BoxLayout:
        orientation: 'vertical'
        Label:            
            text: root.text1
        Label:            
            text: root.text2
        Label:            
            text: root.text3
    Button:
        id: btn1
        text: 'Show Orders'    
        size_hint: .3, .1
       
'''
)

class RowData(GridLayout):
    pass

----------------------------------------------

ElliotG

unread,
Apr 15, 2024, 10:08:28 AMApr 15
to Kivy users support
This file has the key elements.  I changed the id's is a few spots.  The show_info and show_orders methods load the data onto the screens and switch to the desired screen.
The screenmanager is the root widget,  so the root widget is addressed directly, not using the id. 


from kivy.uix.gridlayout import GridLayout
from kivy.properties import StringProperty
from kivy.lang import Builder
from kivy.app import App


Builder.load_string(
'''
<RowData>:
    cols: 3
    size_hint_y: None
    height: 75
    size_hint_x: .8
    spacing: dp(10)
    padding: dp(10)

    Button:
        text: 'info.'
        size_hint_x: .1
        on_release: root.show_info()
    BoxLayout:
        orientation: 'vertical'
        Label:            
            text: root.name  # changed names to match data
        Label:            
            text: root.id
        Label:            
            text: root.phone

    Button:
        id: btn1
        text: 'Show Orders'    
        size_hint: .3, .1
        on_release: root.show_orders()

'''
)


class RowData(GridLayout):
    name = StringProperty()  # added string properties
    id = StringProperty()
    phone = StringProperty()

    def show_info(self):
        # write data to screen 'p3' and set screen to p3
        # access the screen manger to get the desired screen
        # the screen manger is the root widget
        app = App.get_running_app()
        p3 = app.root.get_screen('p3').ids
        p3.name.text = self.name
        p3.id.text = self.id
        p3.phone.text = self.phone
        # change screen
        app.root.current = 'p3'

    def show_orders(self):
        # write data to screen 'p2' and set screen to p2
        app = App.get_running_app()
        p2 = app.root.get_screen('p2').ids
        p2.name.text = self.name
        p2.id.text = self.id
        p2.phone.text = self.phone
        # change screen
        app.root.current = 'p2'

==========================================
in page 1.py:
You can simplify things by having the names of the properties match the names of the keys in the dict and use dictionary unpacking.
class Page1(Screen):
    def __init__(self, **kw):
        super().__init__(**kw)

    def lod_data(self):
        my_lst = [
            {'name': 'Mohamed Ahmed',
             'id': '0001',
             'phone':'0100010001'},

            {'name': 'Sayed Abbas',
             'id': '0002',
             'phone':'0100010002'},

            {'name': 'Abd El-Hamid Shawky',
            'id': '0003',
            'phone':'0100010003'},
        ]
        for lst in my_lst:
            rd1= RowData(**lst)  # changed: unpack dict to set attributes
            self.ids.grid.add_widget(rd1)


I also used RowData directly rather than RD.

In main.py you are deriving classes from Page1-Page3.  You can just use Page1-3 directly. The do not need to be used this way.
You can also put multiple classes in a single file.

I have attached all the code in a zip file.

hans.zip

Han Met

unread,
Apr 15, 2024, 11:15:34 AMApr 15
to Kivy users support
Thanks  ElliotG 
Reply all
Reply to author
Forward
0 new messages