我写了一段处理多个进程的python代码并且它工作得很好,但我试图在这段代码中添加一个基于Kivy的显示。我已经更新了代码,以便能够使用线程而不是进程,这是有效的。我遇到的问题是我似乎无法让线程写回屏幕。我正在使用@mainthread
。我找到了一个示例代码here,并且能够让线程更新屏幕,但由于某种原因,我的代码似乎不起作用。
- >编辑,我删除了我认为与我的问题无关的额外代码。
- >编辑#2:,我仍然将代码简化为我认为裸露的代码。仍然显示我有的问题。根据我的阅读,可能是x.join
代码导致我的问题,并锁定主循环。我需要运行while循环5次,但一次只能运行2个线程。在继续之前,需要在线程完成时将while循环保持在非阻塞状态。
这是menu.kv
<ScreenManagement>:
MenuScreen:
ProgramScreen:
<MenuScreen>:
name: 'menu'
AnchorLayout:
GridLayout:
cols: 2
Button
text: "Start Application"
on_release: root.routine()
<ProgramScreen>:
filler1: filler1
filler2: filler2
filler3: filler3
filler4: filler4
name: 'program'
GridLayout:
cols: 4
Button:
id: filler1
text: 'Filler 1'
halign: 'center'
padding_y: '300'
bcolor: 1,0,1,1
Button:
id: filler2
text: 'Filler 2'
halign: 'center'
padding_y: '300'
bcolor: 1,0,0,1
Button:
id: filler3
text: 'Filler 3'
halign: 'center'
padding_y: '300'
bcolor: 1,0,1,0
Button:
id: filler4
text: 'Filler 4'
halign: 'center'
padding_y: '40 '
bcolor: 0,0,1,1
这是我的main.py
from kivy.app import App
from kivy.uix.togglebutton import ToggleButton
from kivy.uix.widget import Widget
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.gridlayout import GridLayout
from kivy.uix.screenmanager import ScreenManager, Screen, FadeTransition
from kivy.lang import Builder
from kivy.properties import *
from kivy.core.window import Window
from kivy.clock import Clock, mainthread
import threading
import time
########################################################################
class ScreenManagement(ScreenManager):
pass
class MenuScreen(Screen):
def routine(self):
self.parent.current = 'program'
threading.Thread(target=ProgramScreen().build).start()
class ProgramScreen(Screen):
@mainthread
def update_label(self, int_counter, new_text):
if int_counter == 0 :
print "here ", int_counter, new_text
self.filler1.text = new_text
elif int_counter == 1 :
self.filler2.text = new_text
elif int_counter == 2 :
self.filler3.text = new_text
elif int_counter == 3 :
self.filler4.text = new_text
else:
self.filler1.text = "fault"
#dummy function to be replaced with a function that will call GPIO for input and feedback.
def func (self,value):
print 'func', value, 'starting'
for i in xrange(10*(value+1)):
if ((i%3) == 0):
self.update_label(int(value),str(i))
print value, i
time.sleep(1)
print 'func', value, 'finishing'
def build(self):
NumberofFiller = 2
NumberofCells = 5
CellCounter = 0
while CellCounter < NumberofCells:
try:
threads = []
print ('Counter:',CellCounter,'Fillers:',NumberofFiller,'Cells:',NumberofCells)
for i in range (NumberofFiller):
t = threading.Thread(target=self.func, args=((CellCounter%NumberofFiller),))
t.start()
threads.append(t)
CellCounter = CellCounter +1
for x in threads:
#Problem I believe is here.
x.join()
#Need a way to pause the While loop for the first set of threads to finish before starting the next threads.
# print (threads)
except (KeyboardInterrupt, SystemExit):
functions.cleanAndExit()
########################################################################
#Builder.load_file("Menu_red.kv") #Not needed
class Menu_red2App(App):
def build(self):
return ScreenManagement()
#----------------------------------------------------------------------
if __name__ == "__main__":
Menu_red2App().run()
在执行self.parent.current = 'program'
之后,我发现屏幕更新的唯一方法是将其余代码作为线程运行。但我现在似乎无法让线程写回主函数来更新屏幕。最后,一旦文本更新,我将需要更改框的颜色,但这将在适当的时候到来。
答案 0 :(得分:0)
问题在于,当您在routine
方法中启动外部线程时,将目标设置为ProgramScreen().build
,这实际上会创建一个新屏幕。因此,它不会影响您在屏幕管理器中的屏幕
要将目标设置为屏幕管理器中build
的{{1}}方法,您可以按名称获取该屏幕。
你已经给它起了名字ProgramScreen
所以你的program
课应该是这样的:
MenuScreen