我试图在运行这个线程函数后更改屏幕。但它给了我错误
TypeError: Cannot create graphics instruction outside the main Kivy thread
我在网上对此进行了研究,他们告诉我使用时钟属性,但我不知道如何在这里使用它。我只是希望能够通过该命令更改图形指令。但如果我不线程它,应用程序就会没有响应。
这是我的代码:
class Notice(Screen):
def thread_notice(self):
t1 = Thread(target= Notice.sendNotice, args =(self,))
t1.daemon = True
t1.start()
def sendNotice(self):
my_big_chunk_of_code()
kv.current = 'menu'
你不能在主线程之外执行任何 kivy 指令,这意味着你不能在不同的线程上运行 sendNotice,因为它有 kivy 代码...如果
my_big_chunk_of_code()
需要时间,则删除 kv.current = 'menu'
行并将其移动到,例如 thread_notice 函数。
顺便说一下,在线程中,我建议制定目标:
self.sendNotice
而不是Notice.sendNotice
,我认为它创建了该类的另一个实例(不确定),它应该工作相同
我迟到了,但我发布这个答案是为了将来对其他人有所帮助,所以因为你无法在主 Kivy 线程之外创建图形指令,所以你必须对此有点棘手,我面临着同样的问题不久前,这就是我解决这个问题的方法,所以你应该在启动线程之前先创建一个弹出窗口,然后启动你的线程,如果你想在线程内的函数中传递参数,你应该使用像这样的 lambda 函数。
self.showLoadingPopUp() # showing pop up before starting thread
try:
# Using lambda function for passing arguments in function inside thread
threading.Thread(target=lambda : self.yourFunction(argument)).start()
except:
print("Error: unable to start thread")
这不会阻塞您的 UI,当您创建弹出函数时,请确保为此使用类变量,这样您就可以从线程函数中关闭该弹出窗口,这是示例 -
class MyApp(App):
def __init__(self):
super().__init__()
self.window = None
self.loading = None
# Main Build function
def build(self):
self.window = GridLayout()
self.window.cols = 2
return self.window
def showLoadingPopUp(self):
content = BoxLayout(orientation='vertical')
self.loading = Popup(title="Loading", title_color='#FFFFFF', content=content, size=('700dp', '200dp'),
size_hint=(None, None),
auto_dismiss=False,
background='#FFFFFF')
content.add_widget(Label(text="Loading...", color="#FFFFFF"))
def _on_d(*args):
self.loading.is_visable = False
self.loading.bind(on_dismiss=_on_d)
self.loading.is_visable = True
self.loading.open()
while not self.loading.is_visable:
EventLoop.idle()
def yourFunction(self, argument):
for i in list:
# code
self.loading.dismiss() # dismissing old popup
所以简而言之,这个函数将首先创建一个弹出窗口,然后启动一个线程,当我们的工作完成时,线程最终将关闭带有类变量的弹出窗口。希望有帮助。
对我来说,它可以从 kivy.core 导入主线程,然后使用此装饰器设置函数:
喜欢: `
from kivy.clock import mainthread
from kivy.app import App
class MyApp(App):
@mainthread
def create_something(self, *args): # this will run in mainthread, even if called outside.
# cool things created here
`