【问题标题】:Using glfw window inside Pyqt Window在 Pyqt 窗口中使用 glfw 窗口
【发布时间】:2017-09-15 04:18:13
【问题描述】:

我有一个使用 QT 设计器设计的用户界面,并使用 pyqt4 进行了转换。在这个用户界面中,我有表格、选项卡等等......

我还想在该用户界面中添加一个 glfw 窗口,该窗口将与这些表格交互并绘制一些 3D 对象。所以我将在这个 glfw 窗口中使用 pyopengl。我知道如何在单独的窗口中执行此操作,但此窗口必须在其中。有没有办法做到这一点?

谢谢

【问题讨论】:

    标签: python-3.x pyqt4 glfw pyopengl


    【解决方案1】:

    Qt 有一个用于 OpenGL 上下文的内置小部件,称为 QGLWidget,您可以通过它使用典型的 PyOpenGL 命令。您可能想尝试使用它而不是在 GLFW 上下文中硬塞到您的应用程序中。这个answer 应该可以帮助您运行。如果您已经编写了 3D 可视化部分,可能需要进行一些重组,但是,由于要使用此小部件,您需要实现某些功能,例如 initializeGLpaintGL

    编辑:

    至于您在 cmets 中关于处理鼠标事件以启用颜色选择的问题,诀窍是要意识到 QGLWidget 继承自 QWidget。这意味着您可以访问诸如mousePressEvent 之类的功能,您可以实现这些功能。这是我编写的一个简洁的演示(带有一些有用的 cmets),它告诉用户他们点击的位置以及该像素的颜色:

    from OpenGL.GL import *
    from OpenGL.GLU import *
    from PyQt4 import QtGui
    from PyQt4.QtGui import QColor, QStatusBar, QSizePolicy
    from PyQt4.QtOpenGL import *
    import sys
    
    class MainWindow(QtGui.QWidget):
    
        def __init__(self):
            super(MainWindow, self).__init__()
            self.widget = GLWidget(self)
            self.statusbar = QStatusBar()
            self.statusbar.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed)
            self.statusbar.showMessage("Click anywhere on the QGLWidget to see a pixel's RGBA value!")
            layout = QtGui.QVBoxLayout()
            layout.addWidget(self.widget)
            layout.addWidget(self.statusbar)
            layout.setContentsMargins(5, 5, 5, 5)
            self.setLayout(layout)
    
    class GLWidget(QGLWidget):
    
        def __init__(self, parent):
            QGLWidget.__init__(self, parent)
            self.setMinimumSize(640, 480)
            #LMB = left mouse button
            #True: fires mouseMoveEvents even when not holding down LMB
            #False: only fire mouseMoveEvents when holding down LMB
            self.setMouseTracking(False)
    
        def initializeGL(self):
            glClearColor(0, 0, 0, 1)
            glClearDepth(1.0)
            glEnable(GL_DEPTH_TEST)
    
        def resizeGL(self, width, height):
            #glViewport is needed for proper resizing of QGLWidget
            glViewport(0, 0, width, height)
            glMatrixMode(GL_PROJECTION)
            glLoadIdentity()
            glOrtho(0, width, 0, height, -1, 1)
            glMatrixMode(GL_MODELVIEW)
            glLoadIdentity()
    
        def paintGL(self):
            #Renders a triangle... obvious (and deprecated!) stuff
            w, h = self.width(), self.height()
            glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
            glBegin(GL_TRIANGLES)
            glColor3f(1, 0, 0)
            glVertex3f(0, 0, 0)
            glColor3f(0, 1, 0)
            glVertex3f(w/2.0, h, 0)
            glColor3f(0, 0, 1)
            glVertex3f(w, 0, 0)
            glEnd()
    
        def mousePressEvent(self, event):
            x, y = event.x(), event.y()
            w, h = self.width(), self.height()
            #required to call this to force PyQt to read from the correct, updated buffer 
            #see issue noted by @BjkOcean in comments!!!
            glReadBuffer(GL_FRONT)
            data = self.grabFrameBuffer()#builtin function that calls glReadPixels internally
            data.save("test.png")
            rgba = QColor(data.pixel(x, y)).getRgb()#gets the appropriate pixel data as an RGBA tuple
            message = "You selected pixel ({0}, {1}) with an RGBA value of {2}.".format(x, y, rgba)
            statusbar = self.parent().statusbar#goes to the parent widget (main window QWidget) and gets its statusbar widget
            statusbar.showMessage(message)
    
        def mouseMoveEvent(self, event):
            pass
    
        def mouseReleaseEvent(self, event):
            pass
    
    if __name__ == '__main__':
        app = QtGui.QApplication(sys.argv)
        window = MainWindow()
        window.setWindowTitle("Color Picker Demo")
        window.show()
        app.exec_()
    

    结果如下:

    【讨论】:

    • 我可以使用你所指的答案,这个答案只允许我在这个 OpenGL 窗口上绘制 3D 对象。但是,我也想从那个窗口接收信号,我相信只有 glfw 类型的库才允许,对吧?
    • @BjkOcean 我个人没有使用过 GLFW 和 PyQt;我主要使用 sdl2 上下文完成渲染。对于信号,您是在谈论接收键盘和鼠标输入、处理窗口大小调整还是其他不同的东西?
    • 是的,这实际上是我所指的,尤其是从 QGLWidget 中挑选颜色。
    • 非常感谢您的宝贵时间和出色的回应
    • 很抱歉再次打扰您,但我有一个与您的脚本真正相关的小问题。因此,当我运行程序并使窗口大于其初始大小时,一切正常。但是,当它处于初始大小或更小时,颜色选择仅将 RGB 设为 (0,0,0,255),尽管我单击三角形。有什么建议为什么会发生这种情况?
    猜你喜欢
    • 2013-10-24
    • 2020-08-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-10-21
    • 1970-01-01
    • 1970-01-01
    • 2012-08-30
    相关资源
    最近更新 更多