python - Python OpenGL - 线程中没有有效的上下文
问题描述
我有一个要更新显示颜色(RGB)的窗口。为此,我使用 Flask (1.1.1) 接收请求,并使用 Python 3.7 接收窗口的 PyOpenGL (3.1.0)。该系统在 Ubuntu 18.04 上运行。
当只是运行窗口时,它会工作并显示正确的颜色。但是,就像glutMainLoop()
阻塞一样,我想在线程中运行它。
这给了我以下例外:
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
据我在网上找到的,在线程中运行 OpenGL 是可行的,只要一次只有一个线程与 OpenGL 一起运行。我希望主线程运行 Flask 服务器,并且这个线程专门用于调整窗口的颜色。我该如何实施?
下面是在线程中运行的代码:
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()
解决方案
从@Rabbid76 的回答中,很明显从主线程调用 glutInit() 以及我的线程中的所有其他 GLUT 函数都导致了这个问题。这个 SO answer解释了这一点。
为了解决我的问题,我将调用self.init_glut()
移至run()
:
def run(self):
self.init_glut()
glutMainLoop()
现在它就像一个魅力。
推荐阅读
- dns - 用于 Web 配置的正确 CNAME
- r - 如何获得F1、精度、召回和混淆矩阵
- c# - C# 游戏服务器刻度
- snowflake-cloud-data-platform - 向角色添加全局权限时出现问题
- javascript - p元素的Javascript不透明度过渡
- c# - ISet 的命名空间冲突:System.Collections.Generic 和 Iesi.Collections.Generic
- python - ImportError: No module named xgboost and package already installed
- php - PHP:支付宝支付成功,但总额不正确
- hibernate - 休眠/空间的规范/谓词过滤实体,无论它是否在半径内
- c# - 字符串数组列表到数组每个元素的数组