如何将变量从 Class 传递到另一个 Class?
How to pass a variable from Class to another Class?
我正在使用 Kivy 和 Kivymd。我在 class Admin
和 class EditArticle
之间传递变量时遇到问题。我需要将 my_string
从 Admin 传递给 EditArticle。我正在尝试这样做,但得到一个空字符串。
所以,在 class Admin
我有 my_string
。然后,在 class Admin
的方法 edit_article
中,我为 my_string
设置值 'some text'。然后我试图在 class EditArticle
的方法 edit
中获取它。但它一直是空的。实在想不通
- 如果您 运行 我的代码,您将点击顶部菜单
admin
。
- 然后单击任意
mdchip
。
- 然后单击对话框中的 etit 按钮 window。
- 然后点击按钮得到
my_string
(但它总是空的)。
这是我的App.py
from kivy.clock import Clock
from kivymd.app import MDApp
from kivy.properties import StringProperty, NumericProperty
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.uix.boxlayout import BoxLayout
from kivymd.uix.card import MDCard
from kivymd.uix.chip import MDChip
from kivy.core.window import Window
Window.size = (600, 853)
from kivymd.uix.menu import MDDropdownMenu
from kivymd.theming import ThemableBehavior
from kivymd.uix.behaviors import RectangularElevationBehavior
from kivymd.uix.boxlayout import MDBoxLayout
from kivymd.uix.button import MDFlatButton
from kivymd.uix.dialog import MDDialog
class WindowManager(ScreenManager):
pass
class AdminFooter(ThemableBehavior, RectangularElevationBehavior, MDBoxLayout):
def __init__(self, **kwargs):
super().__init__(**kwargs)
self.md_bg_color = self.theme_cls.primary_color
class ToolbarBack(ThemableBehavior, RectangularElevationBehavior, MDBoxLayout):
pass
class CustomToolbar(ThemableBehavior, RectangularElevationBehavior, MDBoxLayout):
def __init__(self, **kwargs):
super().__init__(**kwargs)
self.md_bg_color = self.theme_cls.primary_color
Clock.schedule_once(self.create_menu, 1)
def create_menu(self, i):
self.items = ['admin', 'settings']
menu_items = [{"text": f"{i}"} for i in self.items]
self.menu = MDDropdownMenu(
caller=self.ids.button_2, items=menu_items, width_mult=4, callback=self.get_item
)
def get_item(self, instance):
self.menu.dismiss()
App.get_running_app().window_manager.current = instance.text
class Content(BoxLayout):
pass
class Admin(Screen):
dialog_get_article = None
my_string = StringProperty() # My string
def __init__(self, **kwargs):
super().__init__(**kwargs)
def get_article(self, instance,*args):
self.dialog_get_article = MDDialog(
title="Click the EDIT",
buttons=[
MDFlatButton(
text="EDIT",
on_release = self.edit_article
),
],
)
self.dialog_get_article.open()
def edit_article(self, instance):
self.my_string = 'some text' # set value
App.get_running_app().window_manager.current = 'edit-article'
self.dialog_get_article.dismiss()
def on_enter(self, *args):
data = [
{'id': 1, 'title': 'Arcicle 1', 'body': 'body of Article 1'},
{'id': 2, 'title': 'Arcicle 2', 'body': 'body of Article 2'},
{'id': 3, 'title': 'Arcicle 3', 'body': 'body of Article 3'}
]
for x in data:
chip = BlogChip(id=x.get('id'), title=x.get('title'), body=x.get('body'))
self.ids.box.add_widget(chip)
class EditArticle(Screen):
var = StringProperty()
def edit(self, instance):
print(self.var, ' << it is goingt to be <my_string> from Admin')
class UserSettings(Screen):
pass
class BlogChip(MDChip):
get_admin = Admin()
id = NumericProperty()
title = StringProperty()
body = StringProperty()
class BlogCard(MDCard):
pass
class Detail(Screen):
pass
class ResultSearch(Screen):
pass
class Container(Screen):
def __init__(self, **kwargs):
super().__init__(**kwargs)
Clock.schedule_once(self.create_cards)
def create_cards(self, i):
pass
class App(MDApp):
def callback(self):
self.window_manager.current = 'container'
def build(self):
self.theme_cls.primary_palette = 'Indigo'
self.window_manager = WindowManager()
return self.window_manager
App().run()
我的app.kv
<WindowManager>
Container:
id: scr_1
name: 'container'
Detail:
id: scr_2
name: 'detail'
Admin:
id: scr_3
name: 'admin'
EditArticle:
id: scr_4
name: 'edit-article'
var: scr_3.my_string # <---------
ResultSearch:
id: scr_5
name: 'result-search'
UserSettings:
id: scr_6
name: 'settings'
<Admin>:
BoxLayout:
id: boxlayout_1
orientation: 'vertical'
MDToolbar:
pos_hint: {'top': 1}
title: 'Admin Blog'
left_action_items: [["arrow-left", lambda x: app.callback()]]
ScrollView:
MDStackLayout:
adaptive_height: True
padding: 10
spacing: dp(5)
id: box
<EditArticle>
MDToolbar:
title: 'Admin Blog'
MDLabel:
text: str(root.var)
MDRaisedButton:
text: 'click me to see a variable in console'
pos_hint: {'center_x': .5, 'center_y': .5}
on_release: root.edit(root)
<MyToolbar@CustomToolbar>:
size_hint_y: None
height: self.theme_cls.standard_increment
padding: "25dp"
spacing: "12dp"
MDLabel:
id: label
text: 'Blog'
font_style: 'H6'
theme_text_color: "Custom"
text_color: 1,1,1,1
Widget:
MDIconButton:
id: button_2
icon: "dots-vertical"
pos_hint: {"center_y": .5}
theme_text_color: "Custom"
text_color: 1,1,1,1
on_release: root.menu.open()
<Container>
BoxLayout:
orientation: 'vertical'
MyToolbar:
MDLabel:
text: 'Go To menu (dot-vertical/admin'
halign: 'center'
<BlogCard>
<Detail>:
<BlogChip>
label: root.title
icon: ''
callback: root.get_admin.get_article
我不太明白你的代码在做什么?
为什么不直接看Admin.my_string
里面的EditArticle class
?
如果这不起作用,您是否尝试为您的 my_string
属性创建一个 getter
?
抱歉,我不知道 StringProperty
是如何工作的...但是您不能在 Agent class
中执行以下操作吗?
def get_my_string():
return my_string.value()
然后您只需在 EditArticle
class 中调用 Agent.get_my_string()
。
这是我的问题的解决方案。
我必须将 EditArticle.my_string = self.my_string
添加到 class Admin
,如下所示:
def edit_article(self, instance):
EditArticle.my_string = self.my_string
App.get_running_app().window_manager.current = 'edit-article'
self.dialog_get_article.dismiss()
之后我可以在class EditArticle()
中得到它
根本原因:
在您的应用中,实例化了两个 class Admin
实例。
第一个实例是在您实例化根时在 kv 文件中实例化的,WindowManager()
在 build
方法中。
片段:
<WindowManager>:
...
Admin:
id: scr_3
name: 'admin'
...
第二个实例在class BlogChip
中实例化。
片段:
class BlogChip(MDChip):
get_admin = Admin()
...
class 属性 my_string
已在 class Admin
的第二个实例中更新。
但是屏幕正在引用由根实例化的实例。因此,应用程序显示空字符串。
解决方案:
该解决方案需要更改 kv 和 python 文件。
kv 文件:
替换
callback: root.get_admin.get_article
和
callback: app.root.ids.scr_3.get_article
片段:
<BlogChip>
label: root.title
icon: ''
callback: app.root.ids.scr_3.get_article
Python 文件:
- 删除
class BlogChip(MDChip):
中的 get_admin = Admin()
片段:
class BlogChip(MDChip):
id = NumericProperty()
title = StringProperty()
body = StringProperty()
- 方法中,
edit()
初始化class属性,var
片段:
class EditArticle(Screen):
var = StringProperty()
def edit(self, instance):
# Each screen has by default a property manager that
# gives you the instance of the ScreenManager used.
self.var = self.manager.ids.scr_3.my_string
print(self.var, ' << it is going to be <my_string> from Admin')
输出:
我正在使用 Kivy 和 Kivymd。我在 class Admin
和 class EditArticle
之间传递变量时遇到问题。我需要将 my_string
从 Admin 传递给 EditArticle。我正在尝试这样做,但得到一个空字符串。
所以,在 class Admin
我有 my_string
。然后,在 class Admin
的方法 edit_article
中,我为 my_string
设置值 'some text'。然后我试图在 class EditArticle
的方法 edit
中获取它。但它一直是空的。实在想不通
- 如果您 运行 我的代码,您将点击顶部菜单
admin
。 - 然后单击任意
mdchip
。 - 然后单击对话框中的 etit 按钮 window。
- 然后点击按钮得到
my_string
(但它总是空的)。
这是我的App.py
from kivy.clock import Clock
from kivymd.app import MDApp
from kivy.properties import StringProperty, NumericProperty
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.uix.boxlayout import BoxLayout
from kivymd.uix.card import MDCard
from kivymd.uix.chip import MDChip
from kivy.core.window import Window
Window.size = (600, 853)
from kivymd.uix.menu import MDDropdownMenu
from kivymd.theming import ThemableBehavior
from kivymd.uix.behaviors import RectangularElevationBehavior
from kivymd.uix.boxlayout import MDBoxLayout
from kivymd.uix.button import MDFlatButton
from kivymd.uix.dialog import MDDialog
class WindowManager(ScreenManager):
pass
class AdminFooter(ThemableBehavior, RectangularElevationBehavior, MDBoxLayout):
def __init__(self, **kwargs):
super().__init__(**kwargs)
self.md_bg_color = self.theme_cls.primary_color
class ToolbarBack(ThemableBehavior, RectangularElevationBehavior, MDBoxLayout):
pass
class CustomToolbar(ThemableBehavior, RectangularElevationBehavior, MDBoxLayout):
def __init__(self, **kwargs):
super().__init__(**kwargs)
self.md_bg_color = self.theme_cls.primary_color
Clock.schedule_once(self.create_menu, 1)
def create_menu(self, i):
self.items = ['admin', 'settings']
menu_items = [{"text": f"{i}"} for i in self.items]
self.menu = MDDropdownMenu(
caller=self.ids.button_2, items=menu_items, width_mult=4, callback=self.get_item
)
def get_item(self, instance):
self.menu.dismiss()
App.get_running_app().window_manager.current = instance.text
class Content(BoxLayout):
pass
class Admin(Screen):
dialog_get_article = None
my_string = StringProperty() # My string
def __init__(self, **kwargs):
super().__init__(**kwargs)
def get_article(self, instance,*args):
self.dialog_get_article = MDDialog(
title="Click the EDIT",
buttons=[
MDFlatButton(
text="EDIT",
on_release = self.edit_article
),
],
)
self.dialog_get_article.open()
def edit_article(self, instance):
self.my_string = 'some text' # set value
App.get_running_app().window_manager.current = 'edit-article'
self.dialog_get_article.dismiss()
def on_enter(self, *args):
data = [
{'id': 1, 'title': 'Arcicle 1', 'body': 'body of Article 1'},
{'id': 2, 'title': 'Arcicle 2', 'body': 'body of Article 2'},
{'id': 3, 'title': 'Arcicle 3', 'body': 'body of Article 3'}
]
for x in data:
chip = BlogChip(id=x.get('id'), title=x.get('title'), body=x.get('body'))
self.ids.box.add_widget(chip)
class EditArticle(Screen):
var = StringProperty()
def edit(self, instance):
print(self.var, ' << it is goingt to be <my_string> from Admin')
class UserSettings(Screen):
pass
class BlogChip(MDChip):
get_admin = Admin()
id = NumericProperty()
title = StringProperty()
body = StringProperty()
class BlogCard(MDCard):
pass
class Detail(Screen):
pass
class ResultSearch(Screen):
pass
class Container(Screen):
def __init__(self, **kwargs):
super().__init__(**kwargs)
Clock.schedule_once(self.create_cards)
def create_cards(self, i):
pass
class App(MDApp):
def callback(self):
self.window_manager.current = 'container'
def build(self):
self.theme_cls.primary_palette = 'Indigo'
self.window_manager = WindowManager()
return self.window_manager
App().run()
我的app.kv
<WindowManager>
Container:
id: scr_1
name: 'container'
Detail:
id: scr_2
name: 'detail'
Admin:
id: scr_3
name: 'admin'
EditArticle:
id: scr_4
name: 'edit-article'
var: scr_3.my_string # <---------
ResultSearch:
id: scr_5
name: 'result-search'
UserSettings:
id: scr_6
name: 'settings'
<Admin>:
BoxLayout:
id: boxlayout_1
orientation: 'vertical'
MDToolbar:
pos_hint: {'top': 1}
title: 'Admin Blog'
left_action_items: [["arrow-left", lambda x: app.callback()]]
ScrollView:
MDStackLayout:
adaptive_height: True
padding: 10
spacing: dp(5)
id: box
<EditArticle>
MDToolbar:
title: 'Admin Blog'
MDLabel:
text: str(root.var)
MDRaisedButton:
text: 'click me to see a variable in console'
pos_hint: {'center_x': .5, 'center_y': .5}
on_release: root.edit(root)
<MyToolbar@CustomToolbar>:
size_hint_y: None
height: self.theme_cls.standard_increment
padding: "25dp"
spacing: "12dp"
MDLabel:
id: label
text: 'Blog'
font_style: 'H6'
theme_text_color: "Custom"
text_color: 1,1,1,1
Widget:
MDIconButton:
id: button_2
icon: "dots-vertical"
pos_hint: {"center_y": .5}
theme_text_color: "Custom"
text_color: 1,1,1,1
on_release: root.menu.open()
<Container>
BoxLayout:
orientation: 'vertical'
MyToolbar:
MDLabel:
text: 'Go To menu (dot-vertical/admin'
halign: 'center'
<BlogCard>
<Detail>:
<BlogChip>
label: root.title
icon: ''
callback: root.get_admin.get_article
我不太明白你的代码在做什么?
为什么不直接看Admin.my_string
里面的EditArticle class
?
如果这不起作用,您是否尝试为您的 my_string
属性创建一个 getter
?
抱歉,我不知道 StringProperty
是如何工作的...但是您不能在 Agent class
中执行以下操作吗?
def get_my_string():
return my_string.value()
然后您只需在 EditArticle
class 中调用 Agent.get_my_string()
。
这是我的问题的解决方案。
我必须将 EditArticle.my_string = self.my_string
添加到 class Admin
,如下所示:
def edit_article(self, instance):
EditArticle.my_string = self.my_string
App.get_running_app().window_manager.current = 'edit-article'
self.dialog_get_article.dismiss()
之后我可以在class EditArticle()
根本原因:
在您的应用中,实例化了两个 class Admin
实例。
第一个实例是在您实例化根时在 kv 文件中实例化的,WindowManager()
在 build
方法中。
片段:
<WindowManager>:
...
Admin:
id: scr_3
name: 'admin'
...
第二个实例在class BlogChip
中实例化。
片段:
class BlogChip(MDChip):
get_admin = Admin()
...
class 属性 my_string
已在 class Admin
的第二个实例中更新。
但是屏幕正在引用由根实例化的实例。因此,应用程序显示空字符串。
解决方案:
该解决方案需要更改 kv 和 python 文件。
kv 文件:
替换
callback: root.get_admin.get_article
和
callback: app.root.ids.scr_3.get_article
片段:
<BlogChip>
label: root.title
icon: ''
callback: app.root.ids.scr_3.get_article
Python 文件:
- 删除
class BlogChip(MDChip):
中的
get_admin = Admin()
片段:
class BlogChip(MDChip):
id = NumericProperty()
title = StringProperty()
body = StringProperty()
- 方法中,
edit()
初始化class属性,var
片段:
class EditArticle(Screen):
var = StringProperty()
def edit(self, instance):
# Each screen has by default a property manager that
# gives you the instance of the ScreenManager used.
self.var = self.manager.ids.scr_3.my_string
print(self.var, ' << it is going to be <my_string> from Admin')