Kivy-在子弹出窗口上按一个按钮可以更改父弹出窗口上的标签文本

时间:2020-04-13 15:58:54

标签: python kivy

逻辑:

我按下窗口上的按钮,以打开第一个弹出窗口;

我在第一个弹出窗口上按下一个按钮,以打开第二个弹出窗口;

我按下第二个Popup上的按钮,以调用窗口类中的函数,以更改第一个Popup上的标签文本。

这是示例代码:

from kivy.app import App
from kivy.lang import Builder
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.uix.popup import Popup
from kivy.uix.label import Label
from kivy.uix.button import Button
Builder.load_string("""
<FirstScreen>:
    BoxLayout:
        Button:
            text: 'open the first Popup'
            on_release: root.open_first_popup()
        Button:
            text: 'Quit'

<FirstPopup>:
    first_label: first_label
    BoxLayout:
        orientation: 'vertical'
        Label:
            id: first_label
            text: 'text on first Popup'
        Button:
            text: 'open second Popup'
            on_release: app.access_first_screen.open_second_popup()

<SecondPopup>:
    BoxLayout:
        orientation: 'vertical'
        Label:
            id: second_label
            text: 'text on second Popup'
        Button:
            text: 'change label text on first Popup'
            on_release: app.access_first_screen.change_label_text_on_first_popup()
        Button:
            text: 'close me to check if label text on first Popup has changed'
            on_release: root.close_me()

""")

class FirstPopup(Popup):
    pass

class SecondPopup(Popup):
    def __init__(self, **kwargs):
        super(SecondPopup, self).__init__(**kwargs)

    def close_me(self):
        self.dismiss()

class FirstScreen(Screen):
    def open_first_popup(self):
        the_first_popup = FirstPopup()
        the_first_popup.open()

    def open_second_popup(self):
        the_second_popup = SecondPopup()
        the_second_popup.open()

    def change_label_text_on_first_popup(self):
        app = App.get_running_app()
        app.access_first_screen.the_first_popup.first_label.text = 'change to me'

class Root(ScreenManager):
    def __init__(self, **kwargs):
        super(Root, self).__init__(**kwargs)
        xx = FirstScreen(name='first screen')
        self.add_widget(xx)

class TestApp(App):
    access_first_screen = FirstScreen()
    access_first_popup = FirstPopup()
    def build(self):
        return Root()

if __name__ == '__main__':
    TestApp().run()

现在错误是:

AttributeError:“ FirstScreen”对象没有属性 'the_first_popup'

然后我尝试了:

def change_label_text_on_first_popup(self):
    app = App.get_running_app()
    app.access_first_popup.first_label.text = 'change to me'

没有错误,但“第一个弹出窗口”上的“标签”文本未更改。 然后我尝试了:

def change_label_text_on_first_popup(self):
    app = App.get_running_app()
    app.ids.first_label.text = 'change to me'

错误是: AttributeError:“ TestApp”对象没有属性“ ids”

然后我尝试了:

def change_label_text_on_first_popup(self):
    app = App.get_running_app()
    self.the_first_popup.first_label.text = 'change to me'

错误是: AttributeError:“ FirstScreen”对象没有属性“ the_first_popup”

我无法使其工作。

1 个答案:

答案 0 :(得分:0)

在您的open_first_popup()方法中,使用self.the_first_popup = FirstPopup()。 这样会将the_first_popup保存为实例变量,您以后可以在self.the_first_popup类中以FirstScreen的形式访问。

因此,这是您代码的修改版本:

from kivy.app import App
from kivy.lang import Builder
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.uix.popup import Popup

Builder.load_string("""
#:import Factory kivy.factory.Factory

<FirstScreen>:
    BoxLayout:
        Button:
            text: 'open the first Popup'
            on_release: root.open_first_popup()
        Button:
            text: 'Quit'

<FirstPopup>:
    first_label: first_label
    BoxLayout:
        orientation: 'vertical'
        Label:
            id: first_label
            text: 'text on first Popup'
        Button:
            text: 'open second Popup'
            on_release: Factory.SecondPopup().open()

<SecondPopup>:
    BoxLayout:
        orientation: 'vertical'
        Label:
            id: second_label
            text: 'text on second Popup'
        Button:
            text: 'change label text on first Popup'
            on_release: app.root.get_screen("first screen").change_label_text_on_first_popup()
        Button:
            text: 'close me to check if label text on first Popup has changed'
            on_release: root.close_me()
""")

class FirstPopup(Popup):
    pass

class SecondPopup(Popup):
    def __init__(self, **kwargs):
        super(SecondPopup, self).__init__(**kwargs)

    def close_me(self):
        self.dismiss()

class FirstScreen(Screen):
    def open_first_popup(self):
        self.the_first_popup = FirstPopup()
        self.the_first_popup.open()

    def open_second_popup(self):
        the_second_popup = SecondPopup()
        the_second_popup.open()

    def change_label_text_on_first_popup(self):
        self.the_first_popup.first_label.text = 'change to me'

class Root(ScreenManager):
    def __init__(self, **kwargs):
        super(Root, self).__init__(**kwargs)
        xx = FirstScreen(name='first screen')
        self.add_widget(xx)

class TestApp(App):
    def build(self):
        return Root()

if __name__ == '__main__':
    TestApp().run()

我已删除了access_first_screen,因为这只是创建了一个FirstScreen的新实例,该实例与您的GUI中出现的实例无关。这就是为什么它总是说:

'FirstScreen' object has no attribute 'the_first_popup'

因为FirstScreen的新实例没有这样的属性(GUI中的实例确实有这样的属性)。我还消除了access_first_popup

我也在上面包括了我的建议。