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

dad*_*100 5 python label for-loop kivy

我尝试在for循环中更新标签文本时遇到问题。有类似的条目(例如:在运行代码时更新kivy小部件的属性),但它们似乎与我的问题不完全吻合(或者我错过了重点……)。我运行以下代码:

* .py:

from kivy.app import App
from kivy.uix.boxlayout import BoxLayout
from kivy.properties import StringProperty
#from time import sleep

class MyBox(BoxLayout):
    tobeupd = StringProperty()

    def __init__(self,*args,**kwargs):
        super(MyBox,self).__init__(*args,**kwargs)
        self.tobeupd = '#'

    def upd_ltxt(self):
        for i in range(1,10):
            self.tobeupd = str(i)
            print(self.tobeupd)
            input('Write something: ')  # new line, see edit below
            #sleep(0.5) 

class updApp(App):
    def build(self):
        return MyBox()

if __name__ == '__main__':
    updApp().run() 
Run Code Online (Sandbox Code Playgroud)

* .kv

<MyBox>:
    orientation: 'horizontal'
    cols: 2
    Label:
        text: root.tobeupd
    Button:
        text: 'Start Update'
        on_release: root.upd_ltxt()
Run Code Online (Sandbox Code Playgroud)

尽管'print'语句会定期更新shell,但标签文本仅在for循环的末尾更新。谁能向我解释为什么Kivy会这样工作,以及我如何克服这个问题?

编辑:根据PM2Ring和古加斯,我更改了代码,以避免睡眠功能。如果我要求用户在继续循环之前输入一些内容,问题仍然存在。值在外壳中更新,但不在标签上更新。

el3*_*ien 6

您可以threading为此使用。
当您在 kivy 中执行循环或等待输入时,主线程正在等待,应用程序上不会更新任何内容。threading会阻止这种情况。
使用threading使另一个线程除了主线程。
例子:

from kivy.app import App
from kivy.uix.boxlayout import BoxLayout
from kivy.properties import StringProperty
from kivy.lang import Builder
import threading

Builder.load_string('''

<MyBox>:
    orientation: 'horizontal'
    cols: 2
    Label:
        text: root.tobeupd
    Button:
        text: 'Start Update'
        on_release: root.upd_ltxt()

''')

class MyBox(BoxLayout):
    tobeupd = StringProperty()

    def __init__(self,*args,**kwargs):
        super(MyBox,self).__init__(*args,**kwargs)
        self.tobeupd = '#'

    def upd_ltxt(self):
        threading.Thread(target=self.update_label).start()

    def update_label(self):
        for i in range(1,10):
            print(self.tobeupd)
            self.tobeupd = str(i)
            input('Write something: ')  # new line, see edit below



class updApp(App):
    def build(self):
        return MyBox()

if __name__ == '__main__':
    updApp().run()
Run Code Online (Sandbox Code Playgroud)

现在值得一提的是,您可以继续按下按钮并启动线程,即使第一个尚未完成。这可能是不需要的行为。
这可以通过在线程开始时禁用按钮并在结束时再次启用来防止。

给按钮一个 kv 的 id:

Button:
    id: updatebutton
    text: 'Start Update'
    on_release: root.upd_ltxt()
Run Code Online (Sandbox Code Playgroud)

在线程中这样做:

def update_label(self):

    self.ids.updatebutton.disabled = True

    for i in range(1,10):
        self.tobeupd = str(i)
        input('Write something: ')

    self.ids.updatebutton.disabled = False
Run Code Online (Sandbox Code Playgroud)