如何更新窗口并同时运行后台进程?

问题描述 投票:0回答:1

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个回答
0
投票

通过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)
        # Don't pause main thread with sleep function.
        # 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()


  [1]: https://old.reddit.com/user/adywizard
  [2]: https://old.reddit.com/r/kivy/comments/gc19zn/how_to_update_window_and_simultaneously_run_a/
最新问题
© www.soinside.com 2019 - 2024. All rights reserved.