pythonocc-demos icon indicating copy to clipboard operation
pythonocc-demos copied to clipboard

core_visualization_overpaint_viewer example crash

Open cylopa opened this issue 5 years ago • 4 comments

core_visualization_overpaint_viewer.py crashes at QtGui.QPainter(self)

Same for both Pyside2 5.15.1 and PyQt5 5.12.3.

cylopa avatar Oct 19 '20 09:10 cylopa

Can you please elaborate (trace/os/pyocc version)

tpaviot avatar Oct 19 '20 09:10 tpaviot

Windows 10, pyocc 7.4.0

It prints this:

INFO:OCC.Display.backend:backend loaded: qt-pyqt5
 ###### 3D rendering pipe initialisation #####
Display3d class initialization starting ...
Aspect_DisplayConnection created.
Graphic_Driver created.
V3d_Viewer created.
AIS_InteractiveContext created.
V3d_View created
WNT window created.
Display3d class successfully initialized.
 ########################################

Process finished with exit code -1073740771 (0xC000041D)

It shows only the box, stays a couple seconds frozen then closes.

cylopa avatar Oct 19 '20 10:10 cylopa

I see the paintEngine solves the crash. But it still does not show any bubbles ?

Area zoom doesn't draw the selection box on top of the view.

cylopa avatar Oct 20 '20 07:10 cylopa

QRubberBand seems to be able to draw selection rectangle on top of the view. But any other shape we draw with QPainter in paintEvent does not shown.

Here the examples:

Current behaviour example

import sys

from PySide2.QtWidgets import QApplication, QMainWindow, QRubberBand, QStyleFactory
from PySide2.QtGui import QColor, QPainter, QBrush, QPaintEvent, QResizeEvent, QMouseEvent
from PySide2.QtCore import Qt, QPoint, QRect, QSize
from PySide2.QtOpenGL import QGLWidget

from OCC.Core.Quantity import Quantity_Color, Quantity_TOC_RGB, Quantity_NOC_BLACK
from OCC.Core.V3d import V3d_ZBUFFER, V3d_XposYnegZpos
from OCC.Core.Aspect import Aspect_TOTP_RIGHT_LOWER
from OCC.Core.AIS import AIS_Shaded
from OCC.Core.Visualization import Display3d


class OCCRubberBand(QRubberBand):
    def __init__(self, rubber_band_shape, parent=None):
        super().__init__(rubber_band_shape, parent)

        self.setStyle(QStyleFactory.create("windows"))

    def paintEvent(self, event: QPaintEvent):
        painter = QPainter(self)
        painter.drawRect(event.rect())
        painter.end()


class OCCWidget(QGLWidget):
    def __init__(self, parent=None):
        super().__init__(parent)

        self.origin = QPoint()
        self.rubber_band = OCCRubberBand(QRubberBand.Rectangle, self)

        self.setMouseTracking(True)
        self.setAutoFillBackground(False)
        self.setFocusPolicy(Qt.StrongFocus)
        self.setAttribute(Qt.WA_NativeWindow, True)
        self.setAttribute(Qt.WA_PaintOnScreen, True)
        self.setAttribute(Qt.WA_NoSystemBackground, True)

        display3d = Display3d()
        display3d.Init(self.winId())
        self.display3d = display3d

        self.v3d_viewer = display3d.GetViewer()
        self.v3d_viewer.SetDefaultLights()
        self.v3d_viewer.SetLightOn()

        self.v3d_view = display3d.GetView()
        self.v3d_view.SetBackgroundColor(Quantity_TOC_RGB, 0.34, 0.34, 0.34)
        self.v3d_view.TriedronDisplay(Aspect_TOTP_RIGHT_LOWER, Quantity_Color(Quantity_NOC_BLACK), 0.1, V3d_ZBUFFER)
        self.v3d_view.SetProj(V3d_XposYnegZpos)

        self.ais_context = display3d.GetContext()
        self.ais_context.SetAutomaticHilight(True)
        self.ais_context.SetDisplayMode(AIS_Shaded, False)

        self.prs3d_drawer = self.ais_context.DefaultDrawer()
        self.prs3d_drawer.SetFaceBoundaryDraw(True)

        self.is_resized = False

    def paintEngine(self):
        return None

    def resizeEvent(self, event: QResizeEvent):
        self.is_resized = True

    def paintEvent(self, event: QPaintEvent):
        if self.is_resized:
            self.is_resized = False
            self.v3d_view.MustBeResized()
        else:
            self.v3d_view.Redraw()

        # Does not draw !
        self.makeCurrent()
        painter = QPainter(self)
        self.swapBuffers()
        # This should draw a white filled rectangle.
        rect = QRect(QPoint(100, 100), QPoint(painter.device().width()-100, painter.device().height()-100))
        brush = QBrush()
        brush.setColor(QColor(255, 255, 255))
        brush.setStyle(Qt.SolidPattern)
        painter.fillRect(rect, brush)
        painter.end()
        self.doneCurrent()
        # Does not draw !

    def mousePressEvent(self, event: QMouseEvent):
        self.origin = event.pos()
        self.rubber_band.setGeometry(QRect(self.origin, QSize()))
        self.rubber_band.show()

    def mouseMoveEvent(self, event: QMouseEvent):
        if self.rubber_band.isVisible():
            self.rubber_band.setGeometry(QRect(self.origin, event.pos()).normalized())
            self.update()

    def mouseReleaseEvent(self, event: QMouseEvent):
        if self.rubber_band.isVisible():
            self.rubber_band.hide()


class MainWindow(QMainWindow):
    def __init__(self, parent=None):
        self.q_app = QApplication.instance()
        if self.q_app is None:
            self.q_app = QApplication(sys.argv)

        super().__init__(parent=parent)
        self.setWindowTitle("PyOCC - Overprint example")
        self.resize(1024, 768)

        self.occ_widget = OCCWidget()
        self.setCentralWidget(self.occ_widget)

    def event_loop(self):
        self.show()
        return self.q_app.exec_()


if __name__ == "__main__":
    window = MainWindow()
    sys.exit(window.event_loop())

Desired behaviour example

import sys

from PySide2.QtWidgets import QApplication, QMainWindow, QRubberBand, QStyleFactory
from PySide2.QtGui import QColor, QPainter, QBrush, QPaintEvent, QResizeEvent, QMouseEvent
from PySide2.QtCore import Qt, QPoint, QRect, QSize
from PySide2.QtOpenGL import QGLWidget


class OCCRubberBand(QRubberBand):
    def __init__(self, rubber_band_shape, parent=None):
        super().__init__(rubber_band_shape, parent)

        self.setStyle(QStyleFactory.create("windows"))

    def paintEvent(self, event: QPaintEvent):
        painter = QPainter(self)
        painter.drawRect(event.rect())
        painter.end()


class OCCWidget(QGLWidget):
    def __init__(self, parent=None):
        super().__init__(parent=parent)
        self.origin = QPoint()
        self.rubber_band = OCCRubberBand(QRubberBand.Rectangle, self)

        self.setMouseTracking(True)
        self.setAutoFillBackground(False)
        self.setFocusPolicy(Qt.StrongFocus)
        self.setAttribute(Qt.WA_NativeWindow, True)
        self.setAttribute(Qt.WA_PaintOnScreen, True)
        self.setAttribute(Qt.WA_NoSystemBackground, True)

    # # If we override this method it will not draw the filled rectangles in paintEvent.
    # # But if we do not override while using Display3d then at "painter = QPainter(self)" it crashes.
    # def paintEngine(self):
    #     return None

    def paintEvent(self, event):
        painter = QPainter(self)

        device = painter.device()
        w = device.width()
        h = device.height()
        brush = QBrush()
        brush.setColor(QColor(0, 0, 200))
        brush.setStyle(Qt.SolidPattern)
        painter.fillRect(QRect(QPoint(), QPoint(w, h)), brush)

        rect = QRect(QPoint(100, 100), QPoint(painter.device().width()-100, painter.device().height()-100))
        brush = QBrush()
        brush.setColor(QColor(255, 255, 255))
        brush.setStyle(Qt.SolidPattern)
        painter.fillRect(rect, brush)

        painter.end()

    def mousePressEvent(self, event):
        self.origin = event.pos()
        self.rubber_band.setGeometry(QRect(self.origin, QSize()))
        self.rubber_band.show()

    def mouseMoveEvent(self, event):
        if self.rubber_band.isVisible():
            self.rubber_band.setGeometry(QRect(self.origin, event.pos()).normalized())
            self.update()

    def mouseReleaseEvent(self, event):
        if self.rubber_band.isVisible():
            self.rubber_band.hide()


class MainWindow(QMainWindow):
    def __init__(self, parent=None):
        self.q_app = QApplication.instance()
        if self.q_app is None:
            self.q_app = QApplication(sys.argv)

        super().__init__(parent=parent)
        self.setWindowTitle("PyOCC - Overprint example")
        self.resize(1024, 768)

        self.occ_widget = OCCWidget()
        self.setCentralWidget(self.occ_widget)

    def event_loop(self):
        self.show()
        return self.q_app.exec_()


if __name__ == "__main__":
    window = MainWindow()
    sys.exit(window.event_loop())

cylopa avatar Oct 20 '20 09:10 cylopa