【发布时间】:2020-07-14 10:43:07
【问题描述】:
问题
我有一个循环,在每个段落中都会显示一个弹出窗口。我将其称为popup_A。在循环中有一个条件,当满足时它会同时触发另一个弹出窗口和线程中的方法。这第二个弹出窗口我称之为 popup_B。问题是它确实显示了popup_B,但紧接着popup_A 显示在popup_B 上,完全覆盖了它。为了更好地了解流程的概念:
def myFun:
if condition1:
method1
if condition2:
method2
if condition3:
show popup_B
thread method3
thread popup_A
def popup_A:
do something
display message_A
call myFun
def popup_B:
display message_B
代码 循环中涉及的方法:
def goForward(self):
if self.header == "someTask":
if "tasks" in self.data: # check if the request has "tasks" in the body
if self.counter < len(self.data["tasks"]): # check the counter
self.code = self.data["tasks"][self.counter].get("code")
action = self.data["tasks"][self.counter].get("actionDescription")
if "myCondition" in str(action):
#set the popup structure
self.popup_B = ActivityBox(self)
self.popup_B.open()
# run the method in a thread
t1 = threading.Thread(target = timeConsumingMethod)
t1.start()
# dismiss the popup ActivityBox
self.popup_B.dismiss()
# call popup_A in thread
t3 = threading.Thread(target = self.popup_A)
t3.start()
def do(self):
self.counter = self.counter + 1
self.popup.dismiss()
self.goForward()
def cancel(self):
self.counter = self.counter + 1
self.popup.dismiss()
self.goForward()
def popup_A(self):
self.popup = MessageBox(self)
self.popup.open()
Builder.load_string() 中的 ActivityBox 和 MessageBox 弹出结构:
<MessageBox>:
size_hint: 1, .7
auto_dismiss: False
title: "MessageBoxTitle"
title_align: "center"
title_size: 30
BoxLayout:
orientation: "vertical"
Label:
font_size: '30sp'
text: "MessageBoxLabel"
BoxLayout:
orientation: "horizontal"
spacing: 10
size_hint: 1, .5
Button:
font_size: 50
background_color: 0,204,0,1
text: "CONFIRM"
on_press:
self.disabled = True
self.background_color = 0,255,0,1
app.do()
root.dismiss()
Button:
font_size: 50
background_color: 204,0,0,1
text: "CANCEL"
on_press:
self.background_color = 255,0,0,1
app.cancel()
root.dismiss()
<ActivityBox>:
size_hint: 1, .7
auto_dismiss: False
title: "ActivityBoxTitle"
title_align: "center"
title_size: 30
BoxLayout:
orientation: "vertical"
Label:
font_size: '30sp'
text: "ActivityBoxLabel"
BoxLayout:
orientation: "horizontal"
spacing: 10
size_hint: 1, .5
代码说明
主循环的组件是goForward 和popup_A。随着循环的每一次通过,popup_A 都会出现,并在线程中调用。然后popup_A 回调goForward。如果满足goForward 中的条件“work”,则会显示“work in progress”popup_B。 popup_B 与线程中的方法一起运行,否则 Kivy 不会显示弹出窗口(锁定 GUI)。
结果
到目前为止,我已经尝试过:
- 在线程
t1 = threading.Thread(target = self.popup.open)中运行 popup_B:popup_A 覆盖了 popup_B。 - 使用线程
.join():popup_A 出现但popup_B 没有出现,.join() 忽略它。 - 在一个线程中同时运行 popup_B 和
timeConsumingMethod:popup_A 出现,但 popup_B 不出现。 - 将
timeConsumingMethod作为进程运行:popup_A出现但popup_B没有出现,程序挂起。 - 使用
mutex = threading.Lock()锁定带有popup_B 的线程:popup_A 出现在popup_B 上方。 GUI 也会出现乱码。 - 不在线程中运行 popup_A,而是在线程中同时运行 popup_B 和
timeConsumingMethod:popup_A 出现在 popup_B 上方。
问题
popup_A 只能在线程中的方法完成并且 popup_B 被解除后才会出现。如何防止 popup_A 覆盖 popup_B?
我查看了下面的帖子,但没有找到解决方案。
--- 更新 20200715 --------------------------------------- ---------
在代码中,为了更好地理解,我将 popup_B 中的弹出窗口“正在进行中”和 popup_A 中的 popup2 重命名。
--- 更新 20200716 ---------------------------------------- ----------
我使用Clock.schedule_once 修改了代码,用于step2(用于popup_A 和step3 的线程(用于timeConsumingMethod 和popup_B 的线程)。popup_B 上升但popup_A 覆盖直到最后一个popup_A 被按钮关闭。要等待timeConsumingMethod 完成而不启动popup_A,我使用while loop。代码如下:
def goForward(self):
if self.header == "someTask":
if "tasks" in self.data: # check if the request has "tasks" in the body
if self.counter < len(self.data["tasks"]): # check the counter
self.code = self.data["tasks"][self.counter].get("code")
action = self.data["tasks"][self.counter].get("actionDescription")
if "myCondition" in str(action):
self.returnStatus = 1 # set status
#the two rows below give the same result
#self.popup_B = ActivityBox(self)
#self.popup_B.open()
Clock.schedule_once(self.step3)
# run the method in a thread
t1 = threading.Thread(target = self.step1)
t1.start()
while self.returnStatus != 0:
time.sleep(1)
Cloch.schedule_once(self.step2)
def step1(self):
ts1 = threading.Thread(target = self.timeConsumingMethod)
ts1.start()
ts1.join()
self.returnStatus = 0 # change status when over
return(self.returnStatus)
def step2(self, *args):
ts2 = threading.Thread(target = self.popup_A)
ts2.start()
def step3(self, *args):
#set the popup structure
self.popup = ActivityBox(self)
self.popup.open()
def popup_A(self):
self.popup = MessageBox(self)
t3 = threading.Thread(target = self.popup.open)
t3.start()
def do(self):
self.counter = self.counter + 1
self.popup.dismiss()
self.goForward()
def cancel(self):
self.counter = self.counter + 1
self.popup.dismiss()
exit()
【问题讨论】:
标签: python multithreading popup kivy