【问题标题】:How to update window and simultaneously run a background process?如何更新窗口并同时运行后台进程?
【发布时间】:2020-05-01 21:35:51
【问题描述】:

Python 和 Kivy 的新手。问题可能是不了解 Kivy 的主线程是如何工作的,或者如何添加到主线程中。

以下是为了演示当前问题而编造的代码。

import os
import threading
import http.server
import socketserver
from time import sleep

import kivy
from kivy.app import App
from kivy.clock import Clock
from kivy.lang import Builder
from kivy.properties import NumericProperty
from kivy.uix.screenmanager import ScreenManager, Screen, NoTransition


Builder.load_string("""
<BootstrapScreen>:
    name: 'BootstrapScreen'

    Label:
        ProgressBar:
            id: progress_bar
            max: 5
            size: root.width / 2, 300
            center_x: self.parent.center_x
            center_y: self.parent.center_y

<StartScreen>:
    name: 'StartScreen'

    Label:
        ProgressBar:
            id: progress_bar
            max: 5
            size: root.width / 2, 300
            center_x: self.parent.center_x
            center_y: self.parent.center_y
""")


class BootstrapScreen(Screen):

    progress_bar_value = NumericProperty(0)

    def on_enter(self):
        Clock.schedule_interval(self.update_progress_bar, 1)
        Clock.schedule_once(self.start_server, 0)

    def update_progress_bar(self, dt):
        if self.progress_bar_value < 5:
            self.progress_bar_value += 1
        else:
            self.login()
            return False
        self.ids.progress_bar.value = self.progress_bar_value

    def start_server(self, dt):
        sleep(10)
        self.host = '127.0.0.1'
        self.port = 9999

        self.server = socketserver.TCPServer(
                (self.host, self.port),
                http.server.SimpleHTTPRequestHandler
        )
        self.server_thread = threading.Thread(target=self.server.serve_forever)
        self.server_thread.daemon = True
        self.server_thread.start()

    def login(self):
        App().stop()


class StartScreen(Screen):
    progress_bar_value = NumericProperty(0)

    def on_enter(self):
        Clock.schedule_interval(self.update_progress_bar, 1)

    def update_progress_bar(self, dt):
        if self.progress_bar_value < 5:
            self.progress_bar_value += 1
        else:
            self.bootstrap()
            return False
        self.ids.progress_bar.value = self.progress_bar_value

    def bootstrap(self):
        if not self.manager.has_screen('BootstrapScreen'):
            self.manager.add_widget(BootstrapScreen())
        self.manager.current = 'BootstrapScreen'


class DuoApp(App):
    def build(self):
        screen_manager = ScreenManager(transition=NoTransition())
        screen_manager.add_widget(StartScreen())
        return screen_manager


if __name__ == '__main__':
    DuoApp().run()

应用程序在第一个屏幕上启动。第一个屏幕上是一个自动启动的进度条,大约五秒钟后,应用程序转到第二个屏幕。在第二个屏幕上,还有另一个进度条应该立即启动并且持续大约五秒钟,但它会等到服务器启动后才开始。 (sleep(10) 只是为了展示进度条在进入屏幕时不会立即启动,并且因为实际过程大约需要十秒钟才能完成。)

如何让窗口中的进度条与后台start_server(或任何其他需要十秒钟才能完成的后台进程)同时更新?

【问题讨论】:

  • 请阅读我在您的答案下方留下的评论。此外,您是问题和答案的作者。不接受答案,然后您应该可以删除问题。

标签: python kivy


【解决方案1】:

通过adywizard Reddit ...

# import os
import threading
import http.server
import socketserver
from time import sleep

# import kivy
from kivy.app import App
from kivy.clock import Clock
from kivy.lang import Builder
from kivy.properties import NumericProperty
from kivy.uix.screenmanager import ScreenManager, Screen, NoTransition


Builder.load_string("""
<BootstrapScreen>:
    name: 'BootstrapScreen'

    Label:
        ProgressBar:
            id: progress_bar
            max: 5
            size: root.width / 2, 300
            center_x: self.parent.center_x
            center_y: self.parent.center_y

<StartScreen>:
    name: 'StartScreen'

    Label:
        ProgressBar:
            id: progress_bar
            max: 5
            size: root.width / 2, 300
            center_x: self.parent.center_x
            center_y: self.parent.center_y
""")


class BootstrapScreen(Screen):

    progress_bar_value = NumericProperty(0)

    def on_enter(self):
        Clock.schedule_interval(self.update_progress_bar, 1)
        # Clock.schedule_once(self.start_server, 0)
        # Create a separate thread instead.
        threading.Thread(
            target=self.start_server, daemon=True
        ).start()

    def update_progress_bar(self, dt):
        if self.progress_bar_value < 5:
            self.progress_bar_value += 1
        else:
            self.login()
            return False
        self.ids.progress_bar.value = self.progress_bar_value

    def start_server(self):
        sleep(10)
        self.host = '127.0.0.1'
        self.port = 9999

        self.server = socketserver.TCPServer(
                (self.host, self.port),
                http.server.SimpleHTTPRequestHandler
        )
        self.server_thread = threading.Thread(target=self.server.serve_forever)
        self.server_thread.daemon = True
        self.server_thread.start()

    def login(self):
        App().stop()


class StartScreen(Screen):
    progress_bar_value = NumericProperty(0)

    def on_enter(self):
        Clock.schedule_interval(self.update_progress_bar, 1)

    def update_progress_bar(self, dt):
        if self.progress_bar_value < 5:
            self.progress_bar_value += 1
        else:
            self.bootstrap()
            return False
        self.ids.progress_bar.value = self.progress_bar_value

    def bootstrap(self):
        if not self.manager.has_screen('BootstrapScreen'):
            self.manager.add_widget(BootstrapScreen())
        self.manager.current = 'BootstrapScreen'


class DuoApp(App):
    def build(self):
        screen_manager = ScreenManager(transition=NoTransition())
        screen_manager.add_widget(StartScreen())
        return screen_manager


if __name__ == '__main__':
    DuoApp().run()

【讨论】:

  • 请不要破坏您的帖子。通过在 Stack Exchange 网络上发帖,您已在 CC BY-SA 4.0 license 下授予 Stack Exchange 分发该内容的不可撤销的权利(即无论您未来的选择如何)。根据 Stack Exchange 政策,帖子的非破坏版本是分发的版本,因此,任何破坏行为都将被撤销。如果您想了解更多关于删除帖子的信息,请参阅:How does deleting work?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-11-24
  • 2016-10-20
  • 2017-05-01
相关资源
最近更新 更多