问题
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.
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)
Here is a simplified example of what is going on:
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()
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?
回答1:
screen2.update_label(screen2(),text1, text2)
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)
This will append 10 to this instance of the list.
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.
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)
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.
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.
来源:https://stackoverflow.com/questions/24305280/kivy-label-text-property-doesnt-update-on-the-ui