[英]python | tkinter and threading: “main thread is not in main loop”
我正在为公司使用“多层” GUI来监视温度和状态。 因为我是python编程的新手,所以可以在代码中使用一些帮助。
该代码由类构成。 “主”将打开主窗口(tkinter),并创建其他要显示的框架。 除“画布”外,其他所有类别都是一个框架,它将显示不同的内容。
每个画布包含一个图像和一些文本/可变文本。 线程用于从数据库获取数据并更改画布中的文本。
每次线程访问画布并尝试更改文本或创建新的文本时,都会引发错误"main thread is not in main loop"
。
Exception in thread Thread-1:
Traceback (most recent call last):
File "/usr/lib/python3.4/threading.py", line 920, in _bootstrap_inner
self.run()
File "/usr/lib/python3.4/threading.py", line 868, in run
self._target(*self._args, **self._kwargs)
File "/home/pi/Documents/Programme/MM/TEST_Dateien/TEST_QUEUE.py", line 154, in __call__
canvUbersicht.create_text(500,500, text="HOIIIIII")
File "/usr/lib/python3.4/tkinter/__init__.py", line 2345, in create_text
return self._create('text', args, kw)
File "/usr/lib/python3.4/tkinter/__init__.py", line 2321, in _create
*(args + self._options(cnf, kw))))
RuntimeError: main thread is not in main loop
如果我在不调用画布的情况下初始化线程(例如"print("hey")
),则一切正常。
我的mainloop / mainthread在哪里开始,在哪里结束?
我已经阅读了几个问题并重新排列了代码/线程,但不会改变任何内容。
如果有人可以帮助我,我将非常高兴。
重要代码:
from tkinter import*
from DataSQL import*
class Main(Tk):
def __init__(self, vollbild=False):
print("Main INIT")
Tk.__init__(self) #Initialisieren von Tkinter und somit erzeugen des Fensters
Tk.geometry(self, ("1920x1080")) #setzen von verschiedenen Parametern für das Fenster
Tk.title(self, ("Laborüberwachung"))
Tk.wm_overrideredirect(self, vollbild)
container = Frame(self) #Frame "container" wird im eigenen Objekt(also main fenster) erstellt
container.pack(side="top",fill="both",expand=True) #Platzieren des Frames und ausfüllen des ganzen Fensters
container.grid_rowconfigure(0, weight=1) #Platzieren im Grid
container.grid_columnconfigure(0, weight=1) #Platzieren im Grid
self.frames = {} #Erstellt leere Liste
for F in (Ubersicht, Settings, Pin, BR167, BR213, Star3, Telematik):
frame = F(container, self) #Objekt frame wird erzeugt durch aufruf von Konstruktoren der Klassen(Frameklassen zB "Übersicht")
self.frames[F] = frame #Objekte werden in der Liste gespeichert, unter dem Namen der Klasse(zB "frames[Übersicht]")
frame.grid(row=0, column=0, sticky="nsew") #Platzieren des Frames im Grid, wobei das Grid aus nur einem Feld besteht, wird nur für die Funktionalität benötigt
self.show_frame(Ubersicht) #Zeigt immer die Übersichtsseite bei StartUp
#print(self.frames)
def show_frame(self, cnt): #Methode zum Framewechsel und somit umschalten zwischen 'Tabs'
frame = self.frames[cnt]
frame.tkraise()
print("frame raised",cnt)
class Ubersicht(Frame):
def __init__(self, parent, controller):
print("Ubersicht INIT")
Frame.__init__(self, parent)
self.interfaceImage = PhotoImage(file="/home/pi/Documents/Programme/Laborueberwachung3/IMG 1080/Übersicht.png")
canvUbersicht = canv(self, controller, img=self.interfaceImage, Uber=1)
self.__eventExit = threading.Event()
self.__thread = threading.Thread(target=self, args=(canvUbersicht, self.__eventExit,))
self.__thread.start()
def __call__(self,canvUbersicht,stop_event):
while not stop_event.wait(1):
canvUbersicht.create_text(500,500,text="HEY")
class canv(Canvas):
def __init__(self, parent, controller, img=None, Uber=None):
Canvas.__init__(self, parent)
print("canvas INIT")
self.config(width=1920,height=1080)
self.place(x=0,y=0)
if (img != None):
self.create_image(0,0,anchor=NW,image=img)
if (Uber == 1):
clickAreaSettings = self.create_rectangle(0,0,350,60, fill="", outline="")
self.tag_bind(clickAreaSettings, '<Button-1>',lambda event: controller.show_frame(Pin))
else:
clickAreaBack = self.create_rectangle(0,0,350,60, fill="", outline="")
self.tag_bind(clickAreaBack,'<Button-1>', lambda event: controller.show_frame(Ubersicht))
clickAreaBR167 = self.create_rectangle(0,60,350,315, fill="", outline="")
clickAreaBR213 = self.create_rectangle(0,316,350,570, fill="", outline="")
clickAreaStar3 = self.create_rectangle(0,571,350,825, fill="", outline="")
clickAreaTelematik = self.create_rectangle(0,826,350,1080, fill="", outline="")
self.tag_bind(clickAreaBR167,'<Button-1>', lambda event: controller.show_frame(BR167))
self.tag_bind(clickAreaBR213,'<Button-1>', lambda event: controller.show_frame(BR213))
self.tag_bind(clickAreaStar3,'<Button-1>', lambda event: controller.show_frame(Star3))
self.tag_bind(clickAreaTelematik,'<Button-1>', lambda event: controller.show_frame(Telematik))
app = Main(vollbild=False)
app.mainloop
我的mainloop / mainthread在哪里开始,在哪里结束?
主线程是您没有在另一个线程中显式调用的所有代码。
Tkinter是单线程的,对窗口小部件的所有访问都必须来自同一线程。 当您执行self.__thread = threading.Thread(target=self, ...)
,会导致某些tkinter代码在另一个线程中运行。
您将需要重新编写应用程序,以便数据收集位于单独的线程中,该线程通过线程安全队列与主GUI线程进行通信。 您可以从线程将信息推送到队列中,而gui线程可以轮询队列。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.