繁体   English   中英

如何实时更新 Kivy 滚动视图 Label?

[英]How to update a Kivy Scrollview Label in real time?

对于我实际上非常简单的 Python Kivy 问题,我真的真的需要一些帮助。 我写了一个程序,它首先宣布计数到 5,然后应该开始从 1 计数到 5。信息应该显示在滚动视图标签中。 该代码大致完成了它的工作,但没有逐步更新滚动视图,而是在时间过去后一次全部更新......?有人可以帮忙吗? 先感谢您!

import kivy
from kivy.config import Config
from kivy.app import App
from kivy.uix.label import Label
from kivy.uix.gridlayout import GridLayout
from kivy.uix.button import Button
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.core.window import Window
from kivy.uix.scrollview import ScrollView
import time
 
kivy.require("2.0.0")
Config.set('kivy', 'keyboard_mode', 'systemandmulti')
 
class MainMenu(GridLayout):
    def __init__(self, **kwargs):
        super().__init__(**kwargs)
        self.cols = 1
        self.rows = 2
        
        self.infowindow = ScrollableInfo(height=Window.size[1]*0.8, size_hint_y=None)
        self.add_widget(self.infowindow)
 
        self.ButtonCheckConnection = Button(text="Start Counting to 5")
        self.ButtonCheckConnection.bind(on_press=self.countingtofive)
        self.add_widget(self.ButtonCheckConnection)
 
    def countingtofive(self, *_):
        self.infowindow.update_scrollview(f"Counting to 5 is going to start in 3 seconds")
        time.sleep(3)
        countingmaximum = 5
 
        for i in range(countingmaximum):
            currentnumber = i+1
            self.infowindow.update_scrollview(str(currentnumber))
            time.sleep(1)
 
 
 
class ScrollableInfo(ScrollView):
    def __init__(self, **kwargs):
        super().__init__(**kwargs)
        self.layout = GridLayout(cols=1, size_hint_y=None)
        self.add_widget(self.layout)
 
        self.connectioninfo_history = Label(size_hint_y=None, markup=True)
 
        self.layout.add_widget(self.connectioninfo_history)
 
    def update_scrollview(self, newinfo):
        self.connectioninfo_history.text += '\n' + newinfo
        
        self.layout.height = self.connectioninfo_history.texture_size[1]+15
        self.connectioninfo_history.height = self.connectioninfo_history.texture_size[1]
        self.connectioninfo_history.text_size = (self.connectioninfo_history.width*0.98, None)
 
class Counting(App):
    def build(self):
        self.screen_manager = ScreenManager()
 
        self.mainmenu_page = MainMenu()
        screen = Screen(name="MainMenu")
        screen.add_widget(self.mainmenu_page)
        self.screen_manager.add_widget(screen)
 
        return self.screen_manager
 
if __name__ == "__main__":
    counting_app = Counting()
    counting_app.run()

问题是您正在主线程上运行您的countingtofive()方法。 由于 Kivy 使用主线程来更新 GUI,因此在您释放主线程(通过从countingtofive()方法返回)之前它不能这样做。 这就是为什么在该方法完成之前您什么都看不到的原因。

要解决这个问题,请在另一个线程中运行countingtofive()方法,如下所示:

def start_counting_thread(self, *args):
    Thread(target=self.countingtofive, daemon=True).start()

并将Button更改为绑定到start_counting_thread()方法:

    self.ButtonCheckConnection.bind(on_press=self.start_counting_thread)

update_scrollview()方法的一个小改动(添加@mainthread装饰器):

@mainthread
def update_scrollview(self, newinfo):

@mainthread装饰器强制装饰方法在主线程上运行。 同样可以通过使用Clock.schedule_once()来完成,但装饰器更容易。 只有实际更新 GUI 的那段代码必须在主线程上运行。 通常,您应该尽量避免在主线程上长时间运行方法。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM