示例#1
0
class OpenGLBackend(QGLWidget, OpenGLPlotCanvas):
    _signalRedisplay = pyqtSignal()  # PyQt binds it to instances

    def __init__(self, parent=None, **kw):
        QGLWidget.__init__(self, parent)
        self._signalRedisplay.connect(self.update)

        self.setAutoFillBackground(False)
        self.setMouseTracking(True)

        OpenGLPlotCanvas.__init__(self, parent, **kw)

    def postRedisplay(self):
        """Thread-safe call to QWidget.update."""
        self._signalRedisplay.emit()

    # Mouse events #
    _MOUSE_BTNS = {1: 'left', 2: 'right', 4: 'middle'}

    def sizeHint(self):
        return QSize(8 * 80, 6 * 80)  # Mimic MatplotlibBackend

    def mousePressEvent(self, event):
        xPixel, yPixel = event.x(), event.y()
        btn = self._MOUSE_BTNS[event.button()]
        self.onMousePress(xPixel, yPixel, btn)
        event.accept()

    def mouseMoveEvent(self, event):
        xPixel, yPixel = event.x(), event.y()
        self.onMouseMove(xPixel, yPixel)
        event.accept()

    def mouseReleaseEvent(self, event):
        xPixel, yPixel = event.x(), event.y()
        btn = self._MOUSE_BTNS[event.button()]
        self.onMouseRelease(xPixel, yPixel, btn)
        event.accept()

    def wheelEvent(self, event):
        xPixel, yPixel = event.x(), event.y()
        if hasattr(event, 'angleDelta'):  # Qt 5
            delta = event.angleDelta().y()
        else:  # Qt 4 support
            delta = event.delta()
        angleInDegrees = delta / 8.
        self.onMouseWheel(xPixel, yPixel, angleInDegrees)
        event.accept()

    _CURSORS = {
        CURSOR_DEFAULT: Qt.ArrowCursor,
        CURSOR_POINTING: Qt.PointingHandCursor,
        CURSOR_SIZE_HOR: Qt.SizeHorCursor,
        CURSOR_SIZE_VER: Qt.SizeVerCursor,
        CURSOR_SIZE_ALL: Qt.SizeAllCursor,
    }

    def setCursor(self, cursor=CURSOR_DEFAULT):
        cursor = self._CURSORS[cursor]
        super(OpenGLBackend, self).setCursor(QCursor(cursor))

    # Widget

    def getWidgetHandle(self):
        return self


    # PySide seems to need proxy methods

    def initializeGL(self):
        return OpenGLPlotCanvas.initializeGL(self)

    def paintGL(self):
        return OpenGLPlotCanvas.paintGL(self)

    def resizeGL(self, width, height):
        return OpenGLPlotCanvas.resizeGL(self, width, height)
示例#2
0
class OSMesaGLBackend(QLabel, OpenGLPlotCanvas):
    _signalRedisplay = pyqtSignal()  # PyQt binds it to instances

    _currentContext = None

    def __init__(self, parent=None, **kw):
        # Qt init
        QLabel.__init__(self, parent)
        self._signalRedisplay.connect(self.update)

        self.setAutoFillBackground(False)
        self.setMouseTracking(True)

        # OS Mesa init
        self.__dirtyPixmap = True
        self.__context = mesa.OSMesaCreateContext(mesa.OSMESA_BGRA, None)
        assert self.__context != 0

        # OpenGL Plot backend init
        OpenGLPlotCanvas.__init__(self, parent, **kw)

    def __del__(self):
        mesa.OSMesaDestroyContext(self.__context)

    @classmethod
    def getCurrentContext(cls):
        """Returns the current OSMesa GL context."""
        return cls._currentContext

    def makeCurrent(self):
        """Set the current OSMesa GL context to this instance.
        There is one context per OSMesaGLBackend instance.
        """
        OSMesaGLBackend._currentContext = self

    def postRedisplay(self):
        self.__dirtyPixmap = True
        self._signalRedisplay.emit()

    # Paint #
    def paintEvent(self, event):
        # Only refresh content when paint comes from backend
        if self.__dirtyPixmap:
            self.__dirtyPixmap = False

            height, width = self.__pixmap.shape[0:2]
            assert width == self.size().width()
            assert height == self.size().height()
            errCode = mesa.OSMesaMakeCurrent(self.__context,
                                             self.__pixmap,
                                             gl.GL_UNSIGNED_BYTE,
                                             width,
                                             height)
            assert errCode == gl.GL_TRUE

            self.makeCurrent()
            self.paintGL()
            gl.glFinish()

            image = QImage(self.__pixmap.data, width, height,
                           QImage.Format_ARGB32)
            self.setPixmap(QPixmap.fromImage(image))
        QLabel.paintEvent(self, event)

    def resizeEvent(self, event):
        width, height = self.size().width(), self.size().height()

        # Update underlying pixmap
        self.__dirtyPixmap = True
        self.__pixmap = np.empty((height, width, 4), dtype=np.uint8)
        errCode = mesa.OSMesaMakeCurrent(self.__context,
                                         self.__pixmap,
                                         gl.GL_UNSIGNED_BYTE,
                                         width,
                                         height)
        assert errCode == gl.GL_TRUE
        mesa.OSMesaPixelStore(mesa.OSMESA_Y_UP, 0)

        self.makeCurrent()
        gl.testGL()
        self.initializeGL()
        self.resizeGL(width, height)

        QLabel.resizeEvent(self, event)

    # Mouse events #
    _MOUSE_BTNS = {1: 'left', 2: 'right', 4: 'middle'}

    def sizeHint(self):
        return QSize(8 * 80, 6 * 80)  # Mimic MatplotlibBackend

    def mousePressEvent(self, event):
        xPixel, yPixel = event.x(), event.y()
        btn = self._MOUSE_BTNS[event.button()]
        self.onMousePress(xPixel, yPixel, btn)
        event.accept()

    def mouseMoveEvent(self, event):
        xPixel, yPixel = event.x(), event.y()
        self.onMouseMove(xPixel, yPixel)
        event.accept()

    def mouseReleaseEvent(self, event):
        xPixel, yPixel = event.x(), event.y()
        btn = self._MOUSE_BTNS[event.button()]
        self.onMouseRelease(xPixel, yPixel, btn)
        event.accept()

    def wheelEvent(self, event):
        xPixel, yPixel = event.x(), event.y()
        angleInDegrees = event.delta() / 8.
        self.onMouseWheel(xPixel, yPixel, angleInDegrees)
        event.accept()

    _CURSORS = {
        CURSOR_DEFAULT: Qt.ArrowCursor,
        CURSOR_POINTING: Qt.PointingHandCursor,
        CURSOR_SIZE_HOR: Qt.SizeHorCursor,
        CURSOR_SIZE_VER: Qt.SizeVerCursor,
        CURSOR_SIZE_ALL: Qt.SizeAllCursor,
    }

    def setCursor(self, cursor=CURSOR_DEFAULT):
        cursor = self._CURSORS[cursor]
        QLabel.setCursor(self, QCursor(cursor))

    # Widget handle

    def getWidgetHandle(self):
        return self