让 Kivy 在完成按钮调用的函数执行之前更新 PopUp
Getting Kivy to update PopUp before finishing execution of function called by button
关于问题: 在 sutPopUp.create() 中,我试图让弹出窗口自行更新(删除它的两个按钮并更改“隐藏”标签)。我尝试了对更新函数进行线程化和调用 Clock.schedule_once(self.update_txt, -1)
,但都没有成功。他们似乎都在等待 run_local_command
,这只是一个运行本地命令的阻塞函数。下面是 python 代码:
class sutPopUp(Popup):
pop_float = ObjectProperty(None)
sutPopUp_create = ObjectProperty(None)
sutPopUp_cancel = ObjectProperty(None)
sut_wait_text = ObjectProperty(None)
sutPopUp_input = ObjectProperty(None)
def __init__(self, my_widget,**kwargs):
super(sutPopUp,self).__init__(**kwargs)
self.title = "Test Station Setup"
self.size_hint = (None, None)
self.size = (400, 200)
def create(self, *args):
self.quick_change_thread = threading.Thread(target=self.update_txt)
self.quick_change_thread.start()
time.sleep(1)
sut_name = self.sutPopUp_input.text
create_cmd = "python project.py -c " + sut_name
create_handle = run_local_command(create_cmd, True, "C:\Project")
wm.current = "blank"
wm.remove_widget(screens[2])
screens[2] = Dashboard(name="dashboard_screen")
wm.add_widget(screens[2])
wm.current = "dashboard_screen"
self.dismiss()
self.quick_change_thread.join()
def update_txt(self):
self.sutPopUp_create.disabled = True
self.sutPopUp_cancel.disabled = True
self.pop_float.remove_widget(self.sutPopUp_create)
self.pop_float.remove_widget(self.sutPopUp_cancel)
self.sut_wait_text.text = "Creating Test Station ..."
这是kv:
<sutPopUp@Popup>
pop_float:pop_float
sutPopUp_create:sutPopUp_create
sutPopUp_cancel:sutPopUp_cancel
sut_wait_text:sut_wait_text
sutPopUp_input:sutPopUp_input
FloatLayout:
id: pop_float
size: root.height, root.width
Label:
text: "Enter Test Station Name:"
pos_hint:{"x":0.1,"top":0.9}
size_hint: 0.25, 0.2
TextInput:
id: sutPopUp_input
multiline: False
pos_hint:{"x":0,"top":0.7}
size_hint: 1, 0.2
Label:
id: sut_wait_text
text: ""
pos_hint:{"x":0.4,"top":0.3}
size_hint: 0.25, 0.2
Button:
id: sutPopUp_create
text: "Create"
pos_hint:{"x":0.1,"top":0.3}
size_hint: 0.3, 0.2
on_release: root.create()
Button:
id: sutPopUp_cancel
text: "Cancel"
pos_hint:{"x":0.6,"top":0.3}
size_hint: 0.3, 0.2
on_release: root.dismiss()
我建议将create()
方法分解成三个方法。由于create()
方法是由Button
按下发起的,它会在主线程运行,所以直接调用update_text()
方法即可。然后使用另一个线程来运行 create_cmd
。该新线程然后使用 Clock.schedule_once()
到 运行 原始 create()
方法(新的 finish_create()
方法)中的剩余代码回到主线程。
def create(self, *args):
self.update_text() # this needs to run on the main thread
# time.sleep(1) # ??? this will freeze your app for 1 second
Thread(target=self.do_create).start()
def do_create(self):
sut_name = self.sutPopUp_input.text
create_cmd = "python project.py -c " + sut_name
create_handle = run_local_command(create_cmd, True, "C:\Project")
# after above command completes, run the rest of the former create() back on the main thread
Clock.schedule_once(self.finish_create)
def finish_create(self, dt):
wm.current = "blank"
wm.remove_widget(screens[2])
screens[2] = Dashboard(name="dashboard_screen")
wm.add_widget(screens[2])
wm.current = "dashboard_screen"
self.dismiss()
无论您做什么,当有一个函数占用主线程时,GUI 中的任何内容都不会更新。所以这种方法可以最大限度地减少花在主线程上的时间。此代码未经过测试,因此可能存在错误。但我相信这种方法应该可以实现你想要的。
关于问题: 在 sutPopUp.create() 中,我试图让弹出窗口自行更新(删除它的两个按钮并更改“隐藏”标签)。我尝试了对更新函数进行线程化和调用 Clock.schedule_once(self.update_txt, -1)
,但都没有成功。他们似乎都在等待 run_local_command
,这只是一个运行本地命令的阻塞函数。下面是 python 代码:
class sutPopUp(Popup):
pop_float = ObjectProperty(None)
sutPopUp_create = ObjectProperty(None)
sutPopUp_cancel = ObjectProperty(None)
sut_wait_text = ObjectProperty(None)
sutPopUp_input = ObjectProperty(None)
def __init__(self, my_widget,**kwargs):
super(sutPopUp,self).__init__(**kwargs)
self.title = "Test Station Setup"
self.size_hint = (None, None)
self.size = (400, 200)
def create(self, *args):
self.quick_change_thread = threading.Thread(target=self.update_txt)
self.quick_change_thread.start()
time.sleep(1)
sut_name = self.sutPopUp_input.text
create_cmd = "python project.py -c " + sut_name
create_handle = run_local_command(create_cmd, True, "C:\Project")
wm.current = "blank"
wm.remove_widget(screens[2])
screens[2] = Dashboard(name="dashboard_screen")
wm.add_widget(screens[2])
wm.current = "dashboard_screen"
self.dismiss()
self.quick_change_thread.join()
def update_txt(self):
self.sutPopUp_create.disabled = True
self.sutPopUp_cancel.disabled = True
self.pop_float.remove_widget(self.sutPopUp_create)
self.pop_float.remove_widget(self.sutPopUp_cancel)
self.sut_wait_text.text = "Creating Test Station ..."
这是kv:
<sutPopUp@Popup>
pop_float:pop_float
sutPopUp_create:sutPopUp_create
sutPopUp_cancel:sutPopUp_cancel
sut_wait_text:sut_wait_text
sutPopUp_input:sutPopUp_input
FloatLayout:
id: pop_float
size: root.height, root.width
Label:
text: "Enter Test Station Name:"
pos_hint:{"x":0.1,"top":0.9}
size_hint: 0.25, 0.2
TextInput:
id: sutPopUp_input
multiline: False
pos_hint:{"x":0,"top":0.7}
size_hint: 1, 0.2
Label:
id: sut_wait_text
text: ""
pos_hint:{"x":0.4,"top":0.3}
size_hint: 0.25, 0.2
Button:
id: sutPopUp_create
text: "Create"
pos_hint:{"x":0.1,"top":0.3}
size_hint: 0.3, 0.2
on_release: root.create()
Button:
id: sutPopUp_cancel
text: "Cancel"
pos_hint:{"x":0.6,"top":0.3}
size_hint: 0.3, 0.2
on_release: root.dismiss()
我建议将create()
方法分解成三个方法。由于create()
方法是由Button
按下发起的,它会在主线程运行,所以直接调用update_text()
方法即可。然后使用另一个线程来运行 create_cmd
。该新线程然后使用 Clock.schedule_once()
到 运行 原始 create()
方法(新的 finish_create()
方法)中的剩余代码回到主线程。
def create(self, *args):
self.update_text() # this needs to run on the main thread
# time.sleep(1) # ??? this will freeze your app for 1 second
Thread(target=self.do_create).start()
def do_create(self):
sut_name = self.sutPopUp_input.text
create_cmd = "python project.py -c " + sut_name
create_handle = run_local_command(create_cmd, True, "C:\Project")
# after above command completes, run the rest of the former create() back on the main thread
Clock.schedule_once(self.finish_create)
def finish_create(self, dt):
wm.current = "blank"
wm.remove_widget(screens[2])
screens[2] = Dashboard(name="dashboard_screen")
wm.add_widget(screens[2])
wm.current = "dashboard_screen"
self.dismiss()
无论您做什么,当有一个函数占用主线程时,GUI 中的任何内容都不会更新。所以这种方法可以最大限度地减少花在主线程上的时间。此代码未经过测试,因此可能存在错误。但我相信这种方法应该可以实现你想要的。