I'm working on an "multilayered" GUI for my company to monitor temperature and status. Because I'm quite new to the python programming, I could use some help with my code.
Quick code explanation:
The code is structured by classes. The "Main" inits the main window (tkinter) and creates the other frames to display if wanted. Every other class, except "canvas", is a frame which will display different things.
The canvas in each contains an image and some text/variable text. A thread is used to get data from a database and change the text in the canvas.
The Problem:
Every time, the thread accessed the canvas and tries to change the text or create an new one, the error "main thread is not in main loop"
is thrown.
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
If I init the thread without calling the canvas (e.g. "print("hey")
), everything works fine.
Where does my mainloop / mainthread begin and where do they end?
I have already read several Questions and rearranged the code / thread, but it won't change anything.
I would be really happy, if someone could help me.
important code:
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