Kivy 更新动态标签文本

Posted

技术标签:

【中文标题】Kivy 更新动态标签文本【英文标题】:Kivy Update Dynamic Label Text 【发布时间】:2017-10-08 04:52:17 【问题描述】:

我的目标是查看Popup 上的数字。我有一个 NumericProperty 正在加载。但是,调用回调时数字不会改变。 (我在回调中没有任何代码链接到 label.text)

已提出类似问题。但是,我一直无法看到它们如何适用于这个特定案例。 Similar Case

import kivy
kivy.require("1.7.0")

from kivy.app import App
from kivy.uix.popup import Popup
from kivy.uix.label import Label
from kivy.uix.button import Button
from kivy.uix.boxlayout import BoxLayout
from kivy.properties import ObjectProperty
from kivy.properties import NumericProperty
from kivy.clock import Clock
from kivy.event import EventDispatcher

scoreInc = 0

class MyPopup(Popup):

    def show_popup(self):

        content = BoxLayout(orientation="vertical")

        self.incrementerFnc = Clock.schedule_interval(self.incrementer, .005)

        scoreLabel = Label(text=str(ins.a), id='scorelabel', font_size=20)

        content.add_widget(scoreLabel)

        mybutton = Button(text="Close", size_hint=(1,.20), font_size=20)
        content.add_widget(mybutton)

        mypopup = Popup(content = content,              
                title = "Score",     
                auto_dismiss = False,         
                size_hint = (.7, .5),         
                font_size = 20)
        mybutton.bind(on_press=mypopup.dismiss)  
        mypopup.open()

    def incrementer(self, dt):
        global scoreInc
        scoreInc += 1

        ins.a = scoreInc

        if(scoreInc >= 10):
            Clock.unschedule(self.incrementerFnc)
            print('quit')
        else:
            print('scoreInc', ins.a)    

class MyClass(EventDispatcher):
    a = NumericProperty(0)

def callback(instance, value):
    print('My callback is call from', instance)
    print('and the a value changed to', value)

ins = MyClass()
ins.bind(a=callback)


class MyApp(App):     

    def build(self):

        mypopup = MyPopup()

        return mypopup.show_popup()

if __name__ == "__main__":
    MyApp().run()

【问题讨论】:

【参考方案1】:

您缺少一个更新您的scoreLabel 文本值的事件,您需要在MyClass 中处理该事件,见下文:

class MyClass(EventDispatcher):
    a = NumericProperty(0)
    def on_a(self, instance, value):
        app = App.get_running_app()
        app.scoreLabel.text = str(value)

a 属性更新时,on_a 被触发,然后您可以使用它来更新scoreLabel 值,否则它甚至没有连接。 text = str(ins.a) 行从 ins.a 中获取 并为您使用它,即 0

但是,您需要以某种方式访问​​该scoreLabel,这可能通过例如App.get_running_app() 可以在其中存储实例以供以后使用:

    app = App.get_running_app()
    app.scoreLabel = Label(text=str(ins.a), id='scorelabel', font_size=20)

    content.add_widget(app.scoreLabel)

这样您即使在on_a 事件稍后也可以访问它。或使用self 并直接使用App.get_running_app().popup 访问Popup,然后访问其内容。

App.get_running_app() 但是有时可能不是一个更好的选择,因此您甚至可以使用全局变量或其他方式来存储实例,例如在其他班级内。例如,如果您有 Popup,则该小部件会将自身添加到根 Window 并存储在:

Window -> children -> Popup -> content -> layout -> scoreLabel

但要小心,因为直接弄乱窗口可能会产生不幸的结果。

【讨论】:

【参考方案2】:

对此我会采取不同的方法。 不要使用全局变量,而是将分数作为自定义布局中的属性,并将其传递给弹出窗口。

from kivy.app import App
from kivy.lang import Builder
from kivy.uix.popup import Popup
from kivy.uix.boxlayout import BoxLayout
from kivy.clock import Clock


KV = '''

<MyPopup>:
    title: "Game over"
    score_label: score_label
    id: popup
    content: bl
    BoxLayout:
        id: bl
        Label:
            id: score_label
            text:"Your score is"
            font_size:20
        Button:
            text:"Close this!!"
            on_release: popup.dismiss()


MyLayout:

    orientation: "vertical"
    Label:
        text: "Type in score"
    TextInput:
        id: score_inp
    Button:
        text: "Open gameover popup"
        on_release:
            root.gameover_popup.open()
            root.gameover_popup.gameover(score_inp.text)

'''


class MyPopup(Popup):

    def gameover(self,score):
        self.iterations = int(score)
        self.score = 0
        self.event = Clock.schedule_interval(self.set_label,0.1)

    def set_label(self,dt):
        self.score += 1
        self.score_label.text = str(self.score)
        if self.score >= self.iterations:
            self.event.cancel()



class MyLayout(BoxLayout):

    def __init__(self,**kwargs):
        super(MyLayout,self).__init__(**kwargs) 
        self.gameover_popup = MyPopup()



class MyApp(App):

    def build(self):
        return Builder.load_string(KV)


MyApp().run()

【讨论】:

以上是关于Kivy 更新动态标签文本的主要内容,如果未能解决你的问题,请参考以下文章

Kivy:标签文本在 for 循环期间不更新

Python Kivy:self.ids 不更新标签文本

Kivy ObjectProperty 更新标签文本

Python kivy 更新不同屏幕中的标签文本

更新另一个类中的 kivy 标签文本

如何在 Kivy、Python 中更新标签的文本