问题
我有一个循环,在每个段落中都显示一个弹出窗口。我将其称为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
中的条件“工作”,则显示“正在进行的工作”弹出窗口B。 popup_B与方法一起在线程中运行,否则Kivy不会显示弹出窗口(锁定GUI)。
结果
到目前为止,我已经尝试过:
t1 = threading.Thread(target = self.popup.open)
中运行popup_B:popup_A涵盖了popup_B。.join()
:出现popup_A但没有popup_B,.join()忽略它。timeConsumingMethod
:出现popup_A但没有popup_B。timeConsumingMethod
作为一个过程:出现popup_A但没有popup_B,程序挂起。mutex = threading.Lock()
用popup_B锁定线程:popup_A出现在popup_B上方。同样,GUI也出现乱码。timeConsumingMethod
:popup_A出现在popup_B上方。问题
仅当线程中的方法完成并且popup_B被关闭后,popup_A才能显示。如何防止popup_A覆盖popup_B?
我翻阅了下面的帖子,但没有找到解决方法。
---更新20200715 --------------------------------------- ---------
在代码中,我将 popup_B 中的弹出窗口重命名为“正在进行中”,并在 popup_A 中将popup2重命名为更好的理解。
---更新20200716 --------------------------------------- ----------
我使用Clock.schedule_once
的{{1}}(step2
和popup_A
(step3
和timeConsumingMethod
的线程)修改了代码。 popup_B
上升,但popup_B
覆盖直到用按钮关闭最后一个popup_A
为止,等待popup_A
完成而timeConsumingMethod
结束开火,我使用popup_A
。代码如下:
while loop
答案 0 :(得分:0)
使popup_A在耗时线程完成之前不弹出的一种方法是在耗时线程结束时调用popup_A。尝试将goForward()
方法分为两部分。第一部分几乎保持不变:
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 method in a thread
t1 = threading.Thread(target = self.timeConsumingMethod)
t1.start()
我已经将timeConsumingMethod()
移到了班级,因此需要在self.timeConsumingMethod
中以Thread
的身份进行呼叫。
然后将其余的旧goForward()
方法放在一个单独的方法中(我称之为step2()
):
def step2(self, *args):
# dismiss the popup ActivityBox
self.popup_B.dismiss()
# call popup_A in thread
t3 = threading.Thread(target=self.popup_A)
t3.start()
然后在timeConsumingMethod()
中,在完成时调用step2()
:
def timeConsumingMethod(self):
time.sleep(5)
Clock.schedule_once(self.step2)
答案 1 :(得分:0)
解决方案
我已经通过使用线程解决了弹出窗口重叠的问题。我想这是共享内存和解释器锁的问题。
代码
我修改了代码,并将threading.Thread
添加到绑定到弹出按钮上的方法do(self)
和cancel(self)
中。 step1
在线程中运行timeConsumingMethod
,step2
调用在线程中运行的popup_A,而step3
在线程中运行popup_B。这样popup_A确实会显示,并在popup_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): # check the counter
if "myCondition":
self.step3()
self.step1()
self.popup_A()
def step1(self):
self.popup_A.dismiss() # dismiss the popup A first
ts1 = threading.Thread(target = self.timeConsumingMethod)
ts1.start()
ts1.join()
self.popup_B.dismiss() # dismiss the popup B at the end
def step2(self, *args):
self.popup_A()
def step3(self, *args):
#set the popup structure
self.popup_B = ActivityBox(self)
ts3 = threading.Thread(target = self.popup_B.open)
ts3.start()
ts3.join()
def popup_A(self):
self.popup_A = MessageBox(self)
t3 = threading.Thread(target = self.popup_A.open)
t3.start()
def do(self):
self.counter = self.counter + 1
self.popup_A.dismiss() # dismiss the popup A first
td = threading.Thread(target = self.goForward)
td.start()
def cancel(self):
self.counter = self.counter + 1
self.popup_A.dismiss() # dismiss the popup A first
tc = threading.Thread(target = self.goForward)
tc.start()