简体   繁体   English

Python OpenGL - 线程中没有有效的上下文

[英]Python OpenGL - No valid context in thread

I have a window where I want to update the display color (RGB).我有一个 window 我想更新显示颜色(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.为此,我使用 Flask (1.1.1) 接收请求,并使用 PyOpenGL (3.1.0) 接收 window,使用 ZA7F5F35426B927411FC9231B5638217。 The system is running on Ubuntu 18.04.该系统在 Ubuntu 18.04 上运行。

When just running the window, it works and displays the right color.仅运行 window 时,它可以工作并显示正确的颜色。 However, as glutMainLoop() is blocking, I want to run it in a thread.但是,由于glutMainLoop()阻塞,我想在线程中运行它。

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.据我在网上找到的,只要一次只有一个线程与 OpenGL 一起运行,在一个线程中运行 OpenGL 即可。 I want the main thread to run the Flask server, and this thread dedicated to adjusting the color of the window.我希望主线程运行 Flask 服务器,而这个线程专门用于调整 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.从@Rabbid76 的回答中,很明显从主线程调用 glutInit() 以及从我的线程调用所有其他 GLUT function 导致了这个问题。 This SO answer explained that. 这个 SO answer解释了这一点。

To solve my issue, I moved the call to self.init_glut() to run() :为了解决我的问题,我self.init_glut()的调用移至run()

def run(self):
    self.init_glut()
    glutMainLoop()

Now it works like a charm.现在它就像一个魅力。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM