I have a window where I want to update the display color (RGB). In order to do so, I'm using Flask (1.1.1) to receive the requests, and PyOpenGL (3.1.0) for the window, using Python 3.7. The system is running on Ubuntu 18.04.
When just running the window, it works and displays the right color. However, as glutMainLoop()
is blocking, I want to run it in a thread.
This gives me the following exception:
File "/home/aaa/Desktop/raspberry_pi_display_controller/monitor_manager.py", line 72, in timerFuncWrapper
self.timerFunc(val)
File "/home/aaa/Desktop/raspberry_pi_display_controller/monitor_manager.py", line 78, in timerFunc
glutTimerFunc(val, self.timerFuncWrapper, val)
File "/home/aaa/.local/lib/python3.7/site-packages/OpenGL/GLUT/special.py", line 158, in __call__
callbacks = contextdata.getValue( self.CONTEXT_DATA_KEY )
File "/home/aaa/.local/lib/python3.7/site-packages/OpenGL/contextdata.py", line 104, in getValue
context = getContext( context )
File "/home/aaa/.local/lib/python3.7/site-packages/OpenGL/contextdata.py", line 41, in getContext
"""Attempt to retrieve context when no valid context"""
OpenGL.error.Error: Attempt to retrieve context when no valid context
As far as I could find online, running OpenGL in a thread works, as long as only one thread at a time operates with OpenGL. I want the main thread to run the Flask server, and this thread dedicated to adjusting the color of the window. How can I implement this?
Here is the code for running in a thread:
from OpenGL.GLUT import *
from OpenGL.GL import *
import sys
from threading import Thread, Event
class MonitorManager(Thread):
def __init__(self):
super().__init__()
self.event = Event()
self.window_name = "Pi"
self.red = 1.0
self.blue = 1.0
self.green = 1.0
self.alpha = 1.0
self.init_glut()
def init_glut(self):
glutInit(sys.argv)
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH | GLUT_BORDERLESS | GLUT_CAPTIONLESS)
glutCreateWindow(self.window_name)
glutSetCursor(GLUT_CURSOR_NONE)
glutDisplayFunc(self.displayFuncWrapper)
glutIdleFunc(self.idleFuncWrapper)
glutTimerFunc(0, self.timerFuncWrapper, 100)
def run(self):
glutMainLoop()
def displayFuncWrapper(self):
try:
self.displayFunc()
except Exception as e:
exit(-1)
def displayFunc(self):
glClearColor(self.red, self.green, self.blue, self.alpha)
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT) # clear the screen to the color of glClearColor
glutSwapBuffers()
return
def idleFuncWrapper(self):
try:
self.idleFunc()
except Exception as e:
exit(-1)
def idleFunc(self):
if self.event.is_set():
exit(-1)
def timerFuncWrapper(self, val):
try:
self.timerFunc(val)
except Exception as e:
exit(-1)
def timerFunc(self, val):
self.displayFuncWrapper()
glutTimerFunc(val, self.timerFuncWrapper, val)
def update_colors(self, red, green, blue, alpha):
self.red = red
self.green = green
self.blue = blue
self.alpha = alpha
if __name__ == '__main__':
a = MonitorManager()
a.start()
From @Rabbid76's answer, it became apparent that calling glutInit() from the main thread, and all other GLUT function from my thread caused the issue. This SO answer explained that.
To solve my issue, I moved the call to self.init_glut()
to run()
:
def run(self):
self.init_glut()
glutMainLoop()
Now it works like a charm.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.