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.