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
(或任何其他需要十秒钟才能完成的后台进程)同时在窗口中更新进度条?
# 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/