简体   繁体   English

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

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

I could really really need some help with my actually quite simple Python Kivy Problem.对于我实际上非常简单的 Python Kivy 问题,我真的真的需要一些帮助。 I wrote a program that first announces counting to 5 and then should start counting from 1 to 5. The info should be shown in a scrollview-Label.我写了一个程序,它首先宣布计数到 5,然后应该开始从 1 计数到 5。信息应该显示在滚动视图标签中。 The code roughly does its job but does not update the scrollview step-by-step but all at once after time is elapsed..?can anybody please help?该代码大致完成了它的工作,但没有逐步更新滚动视图,而是在时间过去后一次全部更新......?有人可以帮忙吗? Thank you in advance!先感谢您!

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()

The problem is that you are running your countingtofive() method on the main thread.问题是您正在主线程上运行您的countingtofive()方法。 Since Kivy uses the main thread to update the GUI, it cannot do that until you release the main thread (by returning from the countingtofive() method).由于 Kivy 使用主线程来更新 GUI,因此在您释放主线程(通过从countingtofive()方法返回)之前它不能这样做。 That is why you never see anything until that method completes.这就是为什么在该方法完成之前您什么都看不到的原因。

To fix that, run the countingtofive() method in another thread, like this:要解决这个问题,请在另一个线程中运行countingtofive()方法,如下所示:

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

And change the Button to bind to the start_counting_thread() method:并将Button更改为绑定到start_counting_thread()方法:

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

And one minor change to the update_scrollview() method (add the @mainthread decorator):update_scrollview()方法的一个小改动(添加@mainthread装饰器):

@mainthread
def update_scrollview(self, newinfo):

The @mainthread decorator forces the decorated method to be run on the main thread. @mainthread装饰器强制装饰方法在主线程上运行。 The same can be accomplished by using Clock.schedule_once() , but the decorator is easier.同样可以通过使用Clock.schedule_once()来完成,但装饰器更容易。 Just the piece of the code that actually updates the GUI must be run on the main thread.只有实际更新 GUI 的那段代码必须在主线程上运行。 Generally, you should try to avoid long running methods on the main thread.通常,您应该尽量避免在主线程上长时间运行方法。

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

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