Home > Back-end >  How to access a specific content with ids on kivy
How to access a specific content with ids on kivy

Time:12-11

my problem is that I am doing recycle view of async Images that have a special url. I am loading them thanks to a recycle view. My problem is that I want to print the source of the async image thanks to an app function, on another screen. All I did, didn"t work. The idea is only to recup the source of the async image and to show it on UserInfo screen. Only that. Nb : (The images are taken on an API server.) Thanks !

The code :

class ReviewinApp(MDApp):
    new_dialog = None
    notdialog = None
    dialog =None
    dialoge = None
    asyncimage = None
    doc = None
    data = ListProperty()
    id_ = ListProperty()
    def build(self):
        dialog = None
        self.title = "ReviewinApp"
        global sm 
        sm = ScreenManager()
        sm.add_widget(Builder.load_file("splash.kv"))
        sm.add_widget(Builder.load_file("accueil.kv"))
        sm.add_widget(Builder.load_file('conditions.kv'))
        sm.add_widget(Builder.load_file("register.kv"))
        sm.add_widget(Builder.load_file("faq.kv"))
        sm.add_widget(Builder.load_file("login.kv"))
        sm.add_widget(Builder.load_file("User2.kv"))
        sm.add_widget(Builder.load_file("rules.kv"))
        sm.add_widget(Builder.load_file("commentinput.kv"))
        sm.add_widget(Builder.load_file("UserInfo.kv"))
        sm.add_widget(Builder.load_file('test.kv'))
        return sm
    def load_products(self):
        token = self.token
        json = {"token":token}
        res = requests.post('http://127.0.0.1:2223/products/list', json=json)
        self.doc = res.json()
        self.data = [{'source': 'http://127.0.0.1:2223/products/'   str(self.doc[i].replace('.png', ''))} for i in range(len(self.doc))]
    def en(self):
        app = App.get_running_app()
        print(app.data)
    ```
    MDScreen:
    name: 'test'
    md_bg_color: 41/255, 34/255, 34/255, 1
    on_enter: app.load_products()
    image1: ""
    RecycleView:
        viewclass: "OwnWidget" 
        data: app.data
        RecycleBoxLayout:
            default_size: None, dp(300)
            default_size_hint: 1, None
            size_hint_y: None
            height: self.minimum_height
            orientation: 'vertical'
            spacing: dp(20)
<OwnWidget@BoxLayout>:
    id: recycle
    orientation: 'vertical'
    text: ''
    source:'' 
    MDIconButton:
        icon: 'arrow-left'
        icon_color: 'white'
        theme_icon_color: 'Custom'
        pos_hint: {'center_x':0.3, 'center_y': 0.1}  
        size_hint_x: 0.3
        height: dp(40)
        on_press:
            app.reload_datas()
            app.root.current = "UserInfo"
            print(product.source)
    AsyncImage:
        id: product
        source: root.source
    ```
    MDScreen:
    name: "UserInfo"
    on_enter: app.en()
    MDFloatLayout:
        md_bg_color: 41/255, 34/255, 34/255, 1
        MDLabel:
            id: test_text
            text: ""
    ```

CodePudding user response:

This family of question comes up a lot with kivy, so I have put together a single-file runnable example that you can hopefully get some ideas from.

Regarding the specific question about linking an id; the ids in the .kv code are not available directly in Python but one can make a cross-reference at the top of the kivy object. Here are 4 kivy object ids being connected to Python objects of the same name

<MainScreen>:
    # python names on the left: kivy id on the right
    box_layout_a: box_layout_a
    box_layout_b: box_layout_b
    my_button: my_button
    my_text_input: my_text_input

and here is the reference to the Python objects in the class definition. I like using the type-hints because the IDE can help with auto completion and type checking.

class MainScreen(BoxLayout):
    # python names on the left: kivy id on the right
    box_layout_a: BoxLayout
    box_layout_b: BoxLayout
    my_button: Button
    my_string_property = StringProperty()

Runnable code:

from kivy.lang import Builder
from kivy.app import App
from kivy.uix.button import Button
from kivy.uix.boxlayout import BoxLayout
from kivy.properties import StringProperty
from functools import partial

Builder.load_string('''
<MainScreen>:
    # python names on the left: kivy id on the right
    box_layout_a: box_layout_a
    box_layout_b: box_layout_b
    my_button: my_button
    my_text_input: my_text_input

    orientation: "vertical"
    BoxLayout:
        id: box_layout_a
        orientation: "vertical"
        Button:
            text: "button connected to widget"
            on_press: root.kv_button(1)
        Button:
            text: "button connected to app, increments a counter"
            on_press: app.kv_app_button("method in the top level app")
    BoxLayout:
        id: box_layout_b
        orientation: "horizontal"
        Button:
            id: my_button
        Label:
            id: my_text_input
            text: root.my_string_property
        Label:
            text: app.string_property_bound_in_app
'''
                    )


class MainScreen(BoxLayout):
    # python names on the left: kivy id on the right
    box_layout_a: BoxLayout
    box_layout_b: BoxLayout
    my_button: Button
    my_string_property = StringProperty()

    def function_to_bind(self, my_argument, *args, **kwargs):
        print(f"{self}bound function {my_argument} {args}")

    def __init__(self, **kwargs):
        super().__init__(**kwargs)
        # often you can define the buttons and on_press method in the kivy file
        # but sometimes there are a lot of buttons, and it could makse sense to create them dynamically
        _late_button = Button()
        _late_button.text = "added programatically"
        _late_button.bind(on_press=partial(self.function_to_bind, "custom parameter sent"))
        self.box_layout_a.add_widget(_late_button)

    def kv_button(self, _input, *args) -> None:
        print(f"{self} input {_input}, {args}")
        # This is a little strange, but down here in the widget, we don't have a reference to the App object,
        # however, it can be obtained
        App.get_running_app().string_property_bound_in_app = "hi"


class KivyDemo(App):
    string_property_bound_in_app = StringProperty()

    def __init__(self, **kwargs):
        super().__init__(**kwargs)
        self.count = 0
        # keep a reference to the main screen object
        self.main_box_layout: MainScreen = MainScreen()

    def kv_app_button(self, _input, *args) -> None:
        self.count  = 1
        self.main_box_layout.my_button.text = f"{self.count}"
        self.main_box_layout.my_string_property = f"bound string property {self.count   1}"
        print(f"{self} input: {_input}, {args}")

    def build(self) -> MainScreen:
        return self.main_box_layout

    def on_start(self):
        self.main_box_layout.my_string_property = "initial text"
        self.string_property_bound_in_app = "!"


test: KivyDemo = KivyDemo()
test.run()

CodePudding user response:

All you need to access objects in a different screen is the .get screen() method, the name of the screen, object id, and object property.

  • Related