Kivy Label.text 属性不会在 UI 上更新
问题描述
我遇到了标签的更新文本属性在我的 UI 上未正确显示的问题.我检查了 text 属性并可以验证它是否被设置为新值,但在呈现标签时该值没有显示.
I have an issue with the updated text property of a label not displaying correctly on my UI. I check the text property and can verify that it is being set to the new value but that value isn't being shown when the label is rendered.
标签位于另一个屏幕上,我正在使用 ScreenManager 切换到该屏幕.屏幕的 Sub Widgets 和树是在单独的 .kv 文件中构建的(我在示例中使用了 load_string() Builder 方法,但结果相同)
The Label is on a different Screen which I am switching to using a ScreenManager. The Sub Widgets and tree of the screen are constructed in separate .kv files (I have used the load_string() Builder method in the example but the outcome is the same)
这是一个简单的例子:
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 + '
' + 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 中调用该方法,但无济于事.我错过了什么?
I have tried various things such as changing how i reference the label widget in python, asking the canvas to update or creating a 'screen2()' object to call the method from in the screen1 but to no avail. What is it that I'm missing?
解决方案
screen2.update_label(screen2(),text1, text2)
这一行并不像你想象的那样——实际上,它犯了多个错误,你熟悉 python 类的工作原理吗?
This line doesn't do what you think - actually, it makes multiple mistakes, are you familiar with how python classes work?
首先,当你调用一个方法时,你通常希望用类的实例来做,例如
First, when you call a method, you generally want to do it with an instance of the class, e.g.
a = [1, 2, 3]
a.append(10)
这会将 10 追加到列表的这个 instance.
This will append 10 to this instance of the list.
你所做的不是调用类实例的update_label方法,而是直接用类定义和新实例screen2()
调用.由于这不会为您崩溃,我认为如果您传入要更改的实例,它可能会起作用,但这不正常,也没有理由这样做.问题是您更改了传入的新 screen2 实例的文本,但这与您在应用中实际显示的对象完全不同,因此您看不到任何变化.
What you've done is not call the update_label method of a class instance, but directly called it with the class definition and a new instance screen2()
. Since this didn't crash for you I think it would probably work if you passed in the instance you want to change, but it's not normal and there's no reason to do things this way. The problem is that you changed the text of the new screen2 instance you passed in, but this is a completely different object to the one you're actually displaying in your app, so you see no change.
您需要调用您的应用实际使用的 screen2 实例的 update_label 方法.例如,以下内容应该可以工作:
You instead need to call the update_label method of the screen2 instance your app actually uses. For instance, something like the following should work:
screen2_instance = self.parent.get_screen('screen2')
screen2_instance.update_label(text1, text2)
第一行使用屏幕管理器的 get_screen 方法来检索名为screen2"的现有屏幕.第二行使用您的新文本调用其更新标签方法.请注意,您不传入屏幕实例参数(称为self
) - 实例方法会自动接收第一个参数.
The first line uses the get_screen method of the screenmanager to retrieve the existing screen with the name 'screen2'. The second line calls its update label method with your new text. Note that you do not pass in the screen instance argument (called self
) - an instance method automatically receives this first argument.
你还应该大写你的类名,因为它是一个 python 约定(这显然不是强制性的,但要遵循一般社区风格指南有很多话要说),而且因为 kv 语言使用这种大写来标识小部件,所以如果你不这样做,你以后可能会遇到问题.
You should also capitalise your class names, both because it's a python convention (this is obviously not compulsory but there's a lot to be said for following the general community style guidelines), and because kv language uses this capitalisation to identify widgets so you might hit problems later if you don't do it.
相关文章