Python OpenGL - нет действительного контекста в потоке - PullRequest
1 голос
/ 09 апреля 2020

У меня есть окно, где я хочу обновить цвет дисплея (RGB). Для этого я использую Flask (1.1.1) для получения запросов и PyOpenGL (3.1.0) для окна, используя Python 3.7. Система работает в 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()

1 Ответ

1 голос
/ 09 апреля 2020

Из ответа @ Rabbid76 стало очевидно, что вызов glutInit () из основного потока и всех других функций GLUT из моего потока вызвал проблему. Этот SO-ответ объяснил, что.

Чтобы решить мою проблему, я переместил вызов на self.init_glut() на run():

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

Теперь он работает как очарование.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...