Как передать переменную из класса в другой класс? - PullRequest
0 голосов
/ 11 июля 2020

Я использую Kivy и Kivymd. У меня проблема с передачей переменной между class Admin и class EditArticle. Мне нужно передать my_string от администратора в EditArticle. Я пытаюсь это сделать, но получаю пустую строку. Итак, в class Admin у меня my_string. Затем в методе edit_article из class Admin я устанавливаю значение 'некоторый текст' для my_string. Потом пытаюсь получить его методом edit из class EditArticle. Но он все время пуст. Я действительно не могу это понять.

  1. Если вы запустите мой код, вы нажмете на верхнее меню admin.
  2. Затем нажмите на любой mdchip.
  3. Затем нажмите кнопку etit в диалоговом окне.
  4. Затем нажмите кнопку, чтобы получить 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

Ответы [ 3 ]

2 голосов
/ 12 июля 2020

Root Причина:

В вашем приложении есть два экземпляра class Admin экземпляра.

Этот первый экземпляр был создан в файле kv, когда вы создали экземпляр root , WindowManager() в методе build.

Фрагменты:

<WindowManager>:
    ...

    Admin:
        id: scr_3
        name: 'admin'
    ...

Второй экземпляр был создан в class BlogChip.

Фрагменты:

class BlogChip(MDChip):
    get_admin = Admin()
    ...

Атрибут класса my_string был обновлен во втором экземпляре class Admin. Но экран ссылается на экземпляр, созданный root. Таким образом, приложение отображало пустую строку.

Решение:

Решение требует изменения файлов 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 файл:

  1. Удалите get_admin = Admin() в class BlogChip(MDChip):

Фрагменты:

class BlogChip(MDChip):
    id = NumericProperty()
    title = StringProperty()
    body = StringProperty()
В методе, edit() атрибут инициализации класса, 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')

Вывод:

введите описание изображения здесь

0 голосов
/ 11 июля 2020

Это решение моего вопроса. Мне нужно добавить 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()

0 голосов
/ 11 июля 2020

Я не совсем понимаю, что вы делаете в своем коде?

Почему бы вам не посмотреть прямо Admin.my_string внутри вашего EditArticle class?

Если это не работает , вы пытались создать getter для своего атрибута my_string?
Прошу прощения, я не знаю, как работает StringProperty ... однако вы не можете сделать что-то вроде следующего в Agent class ?

def get_my_string():
    return my_string.value()

Затем вы просто звоните Agent.get_my_string() в свой EditArticle класс.

...