Почему glRotate работает только один раз, когда я не создаю дополнительный класс для своего openGLWidget? - PullRequest
1 голос
/ 11 октября 2019

Я пишу графический интерфейс для отображения выходного сигнала 6-осевого датчика движения с помощью Python. Предполагается, что в окне есть виджет OpenGL, отображающий поворот в реальном времени. Обычно я пишу отдельный класс для моего openGLWidget, но, поскольку в моем пользовательском интерфейсе достаточно много элементов, кажется, что создавать его с нуля нецелесообразно. Вместо этого я просто загружаю файл .ui, нахожу все, что мне нужно, и все. Однако функция glRotate() обновляется только один раз, а затем никогда, и я понятия не имею, что может быть причиной этой проблемы.

from PyQt5 import QtWidgets, uic
from PyQt5.QtCore import *
import OpenGL.GL as gl
import OpenGL.GLU as glu
import sys


class Ui(QtWidgets.QWidget):
    def __init__(self):
        super(Ui, self).__init__()
        uic.loadUi('gl_test.ui', self)

        self.openGLWidget = self.findChild(QtWidgets.QOpenGLWidget, 'openGLWidget')
        self.openGLWidget.initializeGL()
        self.openGLWidget.paintGL = self.paintGL
        self.openGLWidget.initializeGL = self.initializeGL
        self.object = None

        self.rotation = 45.0

#       QTimer for updating the GL Viewport
        self.GLtimer = QTimer()
        self.GLtimer.setInterval(100)
        self.GLtimer.timeout.connect(self.openGLWidget.paintGL)
        self.GLtimer.start()

    def paintGL(self):
        try:
            gl.glClear(gl.GL_COLOR_BUFFER_BIT | gl.GL_DEPTH_BUFFER_BIT)
            gl.glMatrixMode(gl.GL_PROJECTION)
            gl.glLoadIdentity()
            x, y, width, height = gl.glGetDoublev(gl.GL_VIEWPORT)
            glu.gluPerspective(
                45,  # field of view in degrees
                width / float(height or 1),  # aspect ratio
                .25,  # near clipping plane
                200,  # far clipping plane
            )
            gl.glMatrixMode(gl.GL_MODELVIEW)
            gl.glLoadIdentity()
            gl.glTranslated(0.0, 0.0, -10.0)
            self.rotation += 1
            print(self.rotation)
            gl.glRotate(self.rotation, 1, 0, 0)  # works only once for some reason?
            gl.glCallList(self.object)
        except Exception as exc:
            print(exc)
            pass

    def initializeGL(self):
        try:
            # making an example cube
            self.object = gl.glGenLists(1)
            gl.glNewList(self.object, gl.GL_COMPILE)
            gl.glBegin(gl.GL_QUADS)

            gl.glColor3f(0.0, 1.0, 0.0)
            gl.glVertex3f(1.0, 1.0, -1.0)
            gl.glVertex3f(-1.0, 1.0, -1.0)
            gl.glVertex3f(-1.0, 1.0, 1.0)
            gl.glVertex3f(1.0, 1.0, 1.0)

            gl.glColor3f(0.0, 1.0, 0.0)
            gl.glVertex3f(1.0, -1.0, 1.0)
            gl.glVertex3f(-1.0, -1.0, 1.0)
            gl.glVertex3f(-1.0, -1.0, -1.0)
            gl.glVertex3f(1.0, -1.0, -1.0)

            gl.glColor3f(0.0, 1.0, 0.0)
            gl.glVertex3f(1.0, 1.0, 1.0)
            gl.glVertex3f(-1.0, 1.0, 1.0)
            gl.glVertex3f(-1.0, -1.0, 1.0)
            gl.glVertex3f(1.0, -1.0, 1.0)

            gl.glColor3f(0.0, 1.0, 0.0)
            gl.glVertex3f(1.0, -1.0, -1.0)
            gl.glVertex3f(-1.0, -1.0, -1.0)
            gl.glVertex3f(-1.0, 1.0, -1.0)
            gl.glVertex3f(1.0, 1.0, -1.0)

            gl.glColor3f(0.0, 1.0, 0.0)
            gl.glVertex3f(-1.0, 1.0, 1.0)
            gl.glVertex3f(-1.0, 1.0, -1.0)
            gl.glVertex3f(-1.0, -1.0, -1.0)
            gl.glVertex3f(-1.0, -1.0, 1.0)

            gl.glColor3f(0.0, 1.0, 0.0)
            gl.glVertex3f(1.0, 1.0, -1.0)
            gl.glVertex3f(1.0, 1.0, 1.0)
            gl.glVertex3f(1.0, -1.0, 1.0)
            gl.glVertex3f(1.0, -1.0, -1.0)

            gl.glEnd()
            gl.glEndList()

            gl.glEnable(gl.GL_CULL_FACE)
        except Exception as exc:
            print(exc)
            pass


def main():
    app = QtWidgets.QApplication(sys.argv)
    window = Ui()
    window.show()
    app.exec_()


main()

.ui код файла

Эта часть не работает. С ростом self.rotation каждый раз, когда вызывается paintGl() и, следовательно, вызывается glRotate(), я ожидаю, что Куб будет вращаться, но по некоторым причинам это не так.

1 Ответ

1 голос
/ 11 октября 2019

Проблема в событии таймера:

self.GLtimer.timeout.connect(self.openGLWidget.paintGL)

Не рекомендуется вызывать .paintGL напрямую. Обратите внимание, что OpenGL не может ничего рисовать, Контекст OpenGL должен быть актуальным до и после рисования, окно должно быть обновлено. Вы можете увидеть начальный чертеж, потому что первый вызов .paintGL выполняется фреймворком. Следующие вызовы, источником которых является событие timer, не генерируют действительный вывод. Вы должны позвонить .update(), что делает контекст текущим и вызывает триггеры .paintGL(), например:

class Ui(QtWidgets.QWidget):
    def __init__(self):

        # [...]

        self.GLtimer = QTimer()
        self.GLtimer.setInterval(100)
        self.GLtimer.timeout.connect(self.redraw) 
        self.GLtimer.start()

    def redraw(self):
        # updated the widget - triggers paintGL to be called
        self.openGLWidget.update()

Анимация генерируется вашим исходным кодом, за исключением того, что я переключился в режим рисования линий на glPolygonMode.

gl.glPolygonMode(gl.GL_FRONT_AND_BACK, gl.GL_LINE)
...