【问题标题】:Kivy-Press a button on child Popup to change text of Label on parent PopupKivy-按下子弹出窗口上的按钮以更改父弹出窗口上的标签文本
【发布时间】:2020-04-14 23:41:11
【问题描述】:

逻辑:

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

我在第一个 Popup 上按下一个按钮,打开第二个 Popup;

我按下第二个 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'

没有错误,但第一个 Popup 上的 Label 文本没有改变。 然后我尝试了:

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”

我无法让它工作。

【问题讨论】:

  • 在 Python 脚本中定义 ObjectProperty 类型的类属性,例如the_first_popup = ObjectProperty(None), and the_second_popup = ObjectProperty(None)。
  • 嗨@ikolim,我在FirstScreen类中定义了the_first_popup = ObjectProperty(None),然后在def change_label_text_on_first_popup(self):中尝试了一些方法,错误是AttributeError: 'NoneType' object has no attribute 'first_label',仍然无法使其工作。

标签: python kivy


【解决方案1】:

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

所以,这是您的代码的修改版本:

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

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

【讨论】:

  • @John Anderson,谢谢回复,我将 'open_first_popup()' 更改为 def open_first_popup(self): self.the_first_popup = FirstPopup() self.the_first_popup.open() 并将 def change_label_text_on_first_popup(self): 更改为 `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'`错误仍然是'AttributeError:'FirstScreen'对象没有属性'the_first_popup'';如果我使用 `self.the_first_popup.first_label.text = 'change to me'`,错误是一样的。
  • 我在上面的答案中添加了完整的修改代码。
  • 嗨,@约翰·安德森。现在我知道问题在于如何将功能绑定到按钮,而不是功能如何。我从来没有想过这个方向。我用on_release: app.access_first_screen.change_label_text_on_first_popup(),错了;使用你的on_release: app.root.get_screen("first screen").change_label_text_on_first_popup(),正确,有趣。
猜你喜欢
  • 1970-01-01
  • 2017-07-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-05-31
  • 1970-01-01
相关资源
最近更新 更多