kivymd MDProgressBar UI 即使使用线程也不更新

kivymd MDProgressBar UI not updating even with threading

我在 test.py 和 test.kv 中有以下代码。 MDProgressBar UI 直到程序结束才移动。我在 Whosebug 中读过类似的问题,但发布的解决方案只是片段。

假设self.process_some_data()是一个需要很长时间才能完成的函数,MDProgressBar UI实例self.progress_bar 应该反映当前的进度。根据其他论坛帖子的解决方案,我

随时编辑代码并重新发布完整的解决方案。谢谢

main.py

from kivymd.app import MDApp 
from kivymd.uix.progressbar import MDProgressBar 
from kivy.clock import Clock
from kivy.uix.popup import Popup
from kivymd.uix.dialog import MDDialog
from kivy.properties import ObjectProperty
from kivy.lang import Builder
from kivy.uix.screenmanager import Screen
import time
import threading
from kivy.clock import mainthread
from functools import partial

 
class Screen1(Screen):        
    def show_popup(self):
        self.progress_bar = MDProgressBar()
        self.popup = Popup(
            title ='Progress',
            content = self.progress_bar,
            auto_dismiss = False,   # dialog does NOT close if click outside it
            size_hint = (None, None),
            size = (400, 400)
        )
        self.popup.bind( on_open = lambda x: self.run_thread() )
        # self.progress_bar.max = 100
        self.progress_bar.value = 10
        
        self.popup.open()
        print(self.progress_bar.value)

        
    @mainthread
    def update_progress_bar(self, val, _):
        self.progress_bar.value = val
        print(self.progress_bar.value)
        
        if val >= 100:
            # self.popup.dismiss()  
            dialog = MDDialog(title="Status", text="Completed")
            dialog.open()            


    def run_thread(self):
        t1 = threading.Thread(target=self.process_some_data())
        t1.start()
        # t1.join()
        
    def process_some_data(self):          
        time.sleep(1)   # simulate program is running something
        Clock.schedule_once(partial(self.update_progress_bar, 25), 0)

        time.sleep(1)   # simulate program is running something
        Clock.schedule_once(partial(self.update_progress_bar, 50), 0)

        time.sleep(1)   # simulate program is running something
        Clock.schedule_once(partial(self.update_progress_bar, 75), 0)

        time.sleep(1)   # simulate program is running something
        Clock.schedule_once(partial(self.update_progress_bar, 100), 0)

    
# Create the App class 
class MyApp(MDApp):
    def build(self):
        return Builder.load_file("test.kv")
 

# run the App
if __name__ in ("__main__"):
    MyApp().run()

test.kv

Screen1:
        
    Button:
        text: "Run program"
        on_release: root.show_popup()
        size_hint: 0.4, 0.1
        pos_hint: {"center_x": 0.5, "center_y": 0.5}
    

在您的 run_thread() 方法中,行:

t1 = threading.Thread(target=self.process_some_data())

运行 process_some_data() 方法,然后将创建的线程的目标设置为该方法的 return。我认为您只需要从该方法中删除 () ,以便将目标设置为 process_some_data 方法而不是其 return:

t1 = threading.Thread(target=self.process_some_data)