Kivy Label.text属性在UI上不更新

1 投票
1 回答
2171 浏览
提问于 2025-04-18 10:21

我遇到了一个问题,就是我更新的标签文本在界面上显示不正确。我检查了文本属性,确认它已经被设置为新的值,但在标签渲染时,这个值并没有显示出来。

这个标签在一个不同的屏幕上,我是通过一个屏幕管理器来切换到那个屏幕的。这个屏幕的子组件和结构是在不同的.kv文件中构建的(在这个例子中,我使用了load_string()构建方法,但结果是一样的)。

下面是一个简化的例子,说明发生了什么:

from kivy.config import Config
Config.set('graphics', 'width', '300')
Config.set('graphics', 'height', '200')
Config.set('graphics', 'resizable', '0')

from kivy.app import App
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.uix.boxlayout import BoxLayout
from kivy.lang import Builder

Builder.load_string("""
<screen1>:
    Button:
        id: button
        text: 'Press me to Update Screen2'
        on_press:
            root.update_screen2()

<screen2>:
    Label:
        id: mainLabel
        text: 'I have not been updated'
""")

class screen1(Screen):

    def __init__(self, **kwargs):
        """
            Set super and store the id of the button
        """
        super(screen1, self).__init__(**kwargs)
        self.button = self.ids.button.__self__
        return

    def update_screen2(self):
        """
            send text 1 and text 2 to the screen2 object 
            for it to set on it's label
        """
        text1 = 'Hi There'
        text2 = 'Does this work'
        screen2.update_label(screen2(),text1, text2)
        return


class screen2(Screen):

    def __init__(self, **kwargs):
        """
            set super ond store the id of the label
        """
        super(screen2, self).__init__(**kwargs)
        self.mainLabel = self.ids.mainLabel.__self__
        return

    def update_label(self, text1, text2):
        """
            using text1 and text2, update the text property of the label
            the output of each print() shows the text property is being updated
            it just doesn't display on the UI
        """
        print(self.mainLabel.text)
        self.mainLabel.text = text1 + '\n\n' + text2
        print(self.mainLabel.text)
        screenManager.current = 'screen2'
        return

screenManager = ScreenManager()


class MainApp(App):
    def build(self):
        #root widget is abox layout
        self.root = BoxLayout()

        #instantiate the screen objects
        self.screen1 = screen1(name='screen1')
        self.screen2 = screen2(name='screen2')

        #add the screens to the screenManager
        screenManager.add_widget(self.screen1)
        screenManager.add_widget(self.screen2)

        #set the current screen
        screenManager.current = 'screen1'

        #add the screenManager to the root widget and return it
        self.root.add_widget(screenManager)
        return self.root


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

我尝试了各种方法,比如在Python中更改我引用标签组件的方式,要求画布更新,或者创建一个'screen2()'对象来从screen1中调用方法,但都没有成功。我到底遗漏了什么呢?

1 个回答

3
screen2.update_label(screen2(),text1, text2)

这行代码并没有你想的那样工作,实际上它犯了好几个错误,你知道Python类是怎么回事吗?

首先,当你调用一个方法时,通常是想用这个类的一个实例来调用,比如:

a = [1, 2, 3]
a.append(10)

这会把10加到这个实例的列表里。

你所做的并不是调用一个类实例的update_label方法,而是直接用类的定义和一个新的实例screen2()来调用它。既然这没有报错,我觉得如果你传入你想要修改的实例,它可能会工作,但这样做并不正常,也没有必要。问题是你修改了你传入的新screen2实例的文本,但这个实例和你在应用中实际显示的对象是完全不同的,所以你看不到任何变化。

你需要调用你应用中实际使用的screen2实例的update_label方法。例如,像下面这样应该可以:

screen2_instance = self.parent.get_screen('screen2')
screen2_instance.update_label(text1, text2)

第一行使用screenmanager的get_screen方法来获取名为'screen2'的现有屏幕。第二行用你的新文本调用它的更新标签方法。注意,你不需要传入屏幕实例参数(叫self)——实例方法会自动接收这个第一个参数。

你还应该把类名首字母大写,因为这是Python的一个约定(虽然这不是强制的,但遵循社区的风格指南是有好处的),而且kv语言也使用这种大写来识别小部件,如果你不这样做,可能会在后面遇到问题。

撰写回答