[vtkusers] Segfault in vtkOpenGLRenderWindow.OpenGLInitState and advice about render window in/out events

Elvis Stansvik elvis.stansvik at orexplore.com
Mon Jun 27 06:36:22 EDT 2016


2016-06-27 11:08 GMT+02:00 Elvis Stansvik <elvis.stansvik at orexplore.com>:

> 2016-06-27 9:48 GMT+02:00 Elvis Stansvik <elvis.stansvik at orexplore.com>:
>
>> 2016-06-27 9:09 GMT+02:00 Elvis Stansvik <elvis.stansvik at orexplore.com>:
>>
>>> 2016-06-26 13:31 GMT+02:00 Elvis Stansvik <elvis.stansvik at orexplore.com>
>>> :
>>>
>>>> 2016-06-26 13:06 GMT+02:00 Elvis Stansvik <elvis.stansvik at orexplore.com
>>>> >:
>>>>
>>>>> Hi,
>>>>>
>>>>> In my quest to create a PyQt5 widget based on QOpenGLWidget for
>>>>> showing/interacting with VTK, I now have something that seems to work
>>>>> (including the whole thing as a runnable example below).
>>>>>
>>>>
>>>> It was a little too early to say "seems to work": When trying to show
>>>> one of the volumes I need to render, I get
>>>>
>>>> (gui) [estan at pyret orexplore.gui]$ python -m orexplore.gui.main
>>>> enabling depth test
>>>> ERROR: In
>>>> /home/estan/Blandat/vtk-python3/src/VTK-7.0.0/Rendering/OpenGL2/vtkOpenGLRenderWindow.cxx,
>>>> line 1682
>>>> vtkGenericOpenGLRenderWindow (0x308c3f0): Hardware does not support the
>>>> number of textures defined.
>>>>
>>>> Segmentation fault (core dumped)
>>>> (gui) [estan at pyret orexplore.gui]$
>>>>
>>>> on my Sandybridge laptop :/
>>>>
>>>> Anyone know if I'd be able to use the old OpenGL backend here?
>>>>
>>>
>>> I can now confirm that I'm getting the same error on my Haswell work
>>> laptop (which is using the OpenGL2 backend) :( Anyone know if there's a way
>>> to solve this or what I should look into?
>>>
>>> The volume I'm trying to render is not particularly big (2000x120x120,
>>> float), and it renders fine if I use a QGLWidget to back my VTK widget
>>> instead of QOpenGLWidget. So I'm suspecting it might have something to do
>>> with how I set up my QOpenGLWidget.
>>>
>>
>> I tried printing the number of texture units in my StartEvent handler with
>>
>>
>> print(self.renderWindow.GetTextureUnitManager().GetNumberOfTextureUnits())
>>
>> and it print 0, so I think something must definitely be wrong with how I
>> initialize things?
>>
>
> I've now tried from C++, with the QVTKWidget3 class from this
> StackOverflow poster:
>
>     http://stackoverflow.com/a/26946040/252857
>
> which was the inspiration for my own QOpenGLWidget-based PyQt5 widget, and
> I:
>
> - Get the same crash on OpenGLInitState as I mentioned in the start of
> this thread
>
> - If I comment the call to OpenGLInitState, I instead get the following
> crash in VTK when paintGL is called:
>
> (gdb) bt
> #0  0x0000000000000000 in ?? ()
> #1  0x00007ffff7692efd in
> vtkOpenGLRenderWindow::ActivateTexture(vtkTextureObject*) () from
> /opt/VTK-7.0.0/lib/libvtkRenderingOpenGL2-7.0.so.1
> #2  0x00007ffff76d72c8 in vtkTextureObject::Create3DFromRaw(unsigned int,
> unsigned int, unsigned int, int, int, void*) ()
>    from /opt/VTK-7.0.0/lib/libvtkRenderingOpenGL2-7.0.so.1
> #3  0x00007ffff7ba8485 in
> vtkOpenGLGPUVolumeRayCastMapper::vtkInternal::LoadVolume(vtkRenderer*,
> vtkImageData*, vtkVolumeProperty*, vtkDataArray*, int) ()
>    from /opt/VTK-7.0.0/lib/libvtkRenderingVolumeOpenGL2-7.0.so.1
> #4  0x00007ffff7bb123d in
> vtkOpenGLGPUVolumeRayCastMapper::GPURender(vtkRenderer*, vtkVolume*) ()
> from /opt/VTK-7.0.0/lib/libvtkRenderingVolumeOpenGL2-7.0.so.1
> #5  0x00007ffff5ac1615 in vtkGPUVolumeRayCastMapper::Render(vtkRenderer*,
> vtkVolume*) () from /opt/VTK-7.0.0/lib/libvtkRenderingVolume-7.0.so.1
> #6  0x00007ffff5361331 in
> vtkVolume::RenderVolumetricGeometry(vtkViewport*) () from
> /opt/VTK-7.0.0/lib/libvtkRenderingCore-7.0.so.1
> #7  0x00007ffff7694376 in vtkOpenGLRenderer::UpdateGeometry() () from
> /opt/VTK-7.0.0/lib/libvtkRenderingOpenGL2-7.0.so.1
> #8  0x00007ffff7694030 in vtkOpenGLRenderer::DeviceRender() () from
> /opt/VTK-7.0.0/lib/libvtkRenderingOpenGL2-7.0.so.1
> #9  0x00007ffff5341017 in vtkRenderer::Render() () from
> /opt/VTK-7.0.0/lib/libvtkRenderingCore-7.0.so.1
> #10 0x00007ffff533d4c5 in vtkRendererCollection::Render() () from
> /opt/VTK-7.0.0/lib/libvtkRenderingCore-7.0.so.1
> #11 0x00007ffff534705e in vtkRenderWindow::DoStereoRender() () from
> /opt/VTK-7.0.0/lib/libvtkRenderingCore-7.0.so.1
> #12 0x00007ffff534923b in vtkRenderWindow::Render() () from
> /opt/VTK-7.0.0/lib/libvtkRenderingCore-7.0.so.1
> #13 0x00007ffff7693031 in vtkOpenGLRenderWindow::Render() () from
> /opt/VTK-7.0.0/lib/libvtkRenderingOpenGL2-7.0.so.1
> #14 0x00007ffff534ca09 in vtkRenderWindowInteractor::Render() () from
> /opt/VTK-7.0.0/lib/libvtkRenderingCore-7.0.so.1
> #15 0x00000000004079dd in QVTKWidget3::paintGL() ()
> #16 0x00007ffff6e1fdad in QOpenGLWidgetPrivate::invokeUserPaint
> (this=0x6c77f0) at kernel/qopenglwidget.cpp:812
> #17 0x00007ffff6e00f88 in QWidget::event (this=0x7fffffffdba0,
> event=0x7fffffffd080) at kernel/qwidget.cpp:9044
> #18 0x00007ffff6dbe05c in QApplicationPrivate::notify_helper
> (this=this at entry=0x643990, receiver=receiver at entry=0x7fffffffdba0,
> e=e at entry=0x7fffffffd080)
>     at kernel/qapplication.cpp:3716
> #19 0x00007ffff6dc3516 in QApplication::notify (this=0x7fffffffdb90,
> receiver=0x7fffffffdba0, e=0x7fffffffd080) at kernel/qapplication.cpp:3499
> #20 0x00007ffff64cb62b in QCoreApplication::notifyInternal
> (this=0x7fffffffdb90, receiver=receiver at entry=0x7fffffffdba0,
> event=event at entry=0x7fffffffd080)
>     at kernel/qcoreapplication.cpp:965
> #21 0x00007ffff6df9a79 in QCoreApplication::sendSpontaneousEvent
> (event=0x7fffffffd080, receiver=<optimized out>)
>     at ../../include/QtCore/../../src/corelib/kernel/qcoreapplication.h:227
> #22 QWidgetPrivate::sendPaintEvent (this=this at entry=0x6c77f0,
> toBePainted=...) at kernel/qwidget.cpp:5625
> #23 0x00007ffff6dfa0c1 in QWidgetPrivate::drawWidget (this=0x6c77f0,
> pdev=0xcc8ea0, rgn=..., offset=..., flags=flags at entry=5,
>     sharedPainter=sharedPainter at entry=0x0, backingStore=0x808d20) at
> kernel/qwidget.cpp:5565
> #24 0x00007ffff6dcb8aa in QWidgetBackingStore::doSync (this=this at entry=0x808d20)
> at kernel/qwidgetbackingstore.cpp:1226
> #25 0x00007ffff6dcc0a2 in QWidgetBackingStore::sync (this=0x808d20,
> exposedWidget=0x7fffffffdba0, exposedRegion=...) at
> kernel/qwidgetbackingstore.cpp:954
> #26 0x00007ffff6e1da43 in QWidgetWindow::event (this=0x6b3a30,
> event=0x7fffffffd7d0) at kernel/qwidgetwindow.cpp:255
> #27 0x00007ffff6dbe05c in QApplicationPrivate::notify_helper
> (this=this at entry=0x643990, receiver=receiver at entry=0x6b3a30, e=e at entry
> =0x7fffffffd7d0)
>     at kernel/qapplication.cpp:3716
> #28 0x00007ffff6dc3516 in QApplication::notify (this=0x7fffffffdb90,
> receiver=0x6b3a30, e=0x7fffffffd7d0) at kernel/qapplication.cpp:3499
> #29 0x00007ffff64cb62b in QCoreApplication::notifyInternal
> (this=0x7fffffffdb90, receiver=receiver at entry=0x6b3a30, event=event at entry
> =0x7fffffffd7d0)
>     at kernel/qcoreapplication.cpp:965
> #30 0x00007ffff680e4ec in QCoreApplication::sendSpontaneousEvent
> (event=0x7fffffffd7d0, receiver=0x6b3a30)
>     at ../../include/QtCore/../../src/corelib/kernel/qcoreapplication.h:227
> #31 QGuiApplicationPrivate::processExposeEvent (e=0xc55c10) at
> kernel/qguiapplication.cpp:2663
> #32 0x00007ffff680f25d in QGuiApplicationPrivate::processWindowSystemEvent
> (e=e at entry=0xc55c10) at kernel/qguiapplication.cpp:1658
> #33 0x00007ffff67f2f38 in QWindowSystemInterface::sendWindowSystemEvents
> (flags=...) at kernel/qwindowsysteminterface.cpp:625
> #34 0x00007ffff7ec0070 in userEventSourceDispatch (source=<optimized out>)
> at eventdispatchers/qeventdispatcher_glib.cpp:70
> #35 0x00007ffff0643127 in g_main_context_dispatch () from
> /lib/x86_64-linux-gnu/libglib-2.0.so.0
> #36 0x00007ffff0643380 in ?? () from /lib/x86_64-linux-gnu/libglib-2.0.so.0
> #37 0x00007ffff064342c in g_main_context_iteration () from
> /lib/x86_64-linux-gnu/libglib-2.0.so.0
> #38 0x00007ffff6521a7f in QEventDispatcherGlib::processEvents
> (this=0x6966d0, flags=...) at kernel/qeventdispatcher_glib.cpp:418
> #39 0x00007ffff64c8dea in QEventLoop::exec (this=this at entry=0x7fffffffda90,
> flags=..., flags at entry=...) at kernel/qeventloop.cpp:204
> #40 0x00007ffff64d0e8c in QCoreApplication::exec () at
> kernel/qcoreapplication.cpp:1229
> #41 0x00000000004066e1 in main ()
>
> I noticed the crash is in ActivateTexture. Could this be due to the same
> texture unit problem I saw when using my Python widget?
>

I've now made a minimal C++ test case. It uses the QVTKWidget3 class from
[1] http://stackoverflow.com/a/26946040/252857 , but exhibits the same
crashing behavior as my (similar) Python widget.

The test case can be downloaded via

    https://dl.dropboxusercontent.com/u/22350696/test_vtkwidget3.tar.bz2

and includes a test volume.

Build and run the test case with

mkdir build
cd build
cmake ..
make
./TestVTKWidget3 ../volume.vtk

By default, the test case uses a plain render window, and works fine.

But if you uncomment

# Uncomment to try out QVTKWidget3
# add_definitions(-DUSE_QVTKWIDGET3)

in CMakeLists.txt and rebuild, it will instead use QVTKWidget3 from the
above StackOverflow.

In this mode the test case either:

- Crashes in vtkOpenGLRenderWindow::ActivateTexture, if the OpenGLInitState
call in QVTKWidget3 is commented
- Crashes in OpenGLInitState if it is uncommented

I would be very grateful if someone could run this test case and see if
they can reproduce (preferably on Intel graphics).

Elvis


> Elvis
>
>
>> Elvis
>>
>>
>>>
>>> What I'm doing to configure it is simply:
>>>
>>>         # Request OpenGL 3.2 compatibility profile and enable
>>> multi-sampling
>>>         surfaceFormat = QSurfaceFormat.defaultFormat()
>>>         surfaceFormat.setMajorVersion(3)
>>>         surfaceFormat.setMinorVersion(2)
>>>         surfaceFormat.setProfile(QSurfaceFormat.CompatibilityProfile)
>>>         surfaceFormat.setSamples(8)
>>>         self.setFormat(surfaceFormat)
>>>
>>> The whole reason I'm trying to get QOpenGLWidget working is that
>>> QGLWidget does not have a setFormat in PyQt5, since it doesn't wrap
>>> functions marked "obsolete" in Qt, and this prevents me from enabling
>>> multi-sampling.
>>>
>>> Very grateful for any advice from experts on the OpenGL2 backend, as I
>>> really need to get this working and move on.
>>>
>>> I'm attaching my vtk_widget2.py, which shows how I set up rendering into
>>> the QOpenGLWidget. Rendering of the cone example at the bottom works, it's
>>> just when I'm trying volume rendering using vtkGPUVolumeRayCastMapper that
>>> I get the above error.
>>>
>>> Elvis
>>>
>>>
>>>> Elvis
>>>>
>>>>
>>>>>
>>>>> I do however have two problems (indicated by "FIXME:"s in the code
>>>>> below):
>>>>>
>>>>> 1. When I try to call vtkOpenGLRenderWindow.OpenGLInitState when
>>>>> handling the render window StartEvent (commented out below), similar to how
>>>>> QVTKWidget2 does, I get a segmentation fault:
>>>>>
>>>>> (gdb) bt
>>>>> #0  0x0000000000000000 in ?? ()
>>>>> #1  0x00007fffd8ad13b9 in vtkOpenGLRenderWindow::OpenGLInitState() ()
>>>>> from /usr/lib/libvtkRenderingOpenGL2.so.1
>>>>> #2  0x00007fffd8de8479 in ?? () from
>>>>> /usr/lib/libvtkRenderingOpenGL2Python35D.so.1
>>>>> #3  0x00007ffff79ba5e9 in PyCFunction_Call () from
>>>>> /usr/lib/libpython3.5m.so.1.0
>>>>> #4  0x00007ffff7a325f1 in PyEval_EvalFrameEx () from
>>>>> /usr/lib/libpython3.5m.so.1.0
>>>>> #5  0x00007ffff7a339e2 in ?? () from /usr/lib/libpython3.5m.so.1.0
>>>>> #6  0x00007ffff7a33ac3 in PyEval_EvalCodeEx () from
>>>>> /usr/lib/libpython3.5m.so.1.0
>>>>> #7  0x00007ffff799db98 in ?? () from /usr/lib/libpython3.5m.so.1.0
>>>>> #8  0x00007ffff79730da in PyObject_Call () from
>>>>> /usr/lib/libpython3.5m.so.1.0
>>>>> #9  0x00007ffff7989d64 in ?? () from /usr/lib/libpython3.5m.so.1.0
>>>>> #10 0x00007ffff79730da in PyObject_Call () from
>>>>> /usr/lib/libpython3.5m.so.1.0
>>>>> #11 0x00007ffff7a2a457 in PyEval_CallObjectWithKeywords () from
>>>>> /usr/lib/libpython3.5m.so.1.0
>>>>> #12 0x00007fffe8d905a0 in vtkPythonCommand::Execute(vtkObject*,
>>>>> unsigned long, void*) () from /usr/lib/libvtkWrappingPython35Core.so.1
>>>>> #13 0x00007fffe89ac196 in ?? () from /usr/lib/libvtkCommonCore.so.1
>>>>> #14 0x00007fffdf022a0f in vtkRenderWindow::Render() () from
>>>>> /usr/lib/libvtkRenderingCore.so.1
>>>>> #15 0x00007fffd8ad4461 in vtkOpenGLRenderWindow::Render() () from
>>>>> /usr/lib/libvtkRenderingOpenGL2.so.1
>>>>> #16 0x00007fffdf027498 in vtkRenderWindowInteractor::Start() () from
>>>>> /usr/lib/libvtkRenderingCore.so.1
>>>>> #17 0x00007fffdf3ee789 in ?? () from
>>>>> /usr/lib/libvtkRenderingCorePython35D.so.1
>>>>> #18 0x00007ffff79ba5e9 in PyCFunction_Call () from
>>>>> /usr/lib/libpython3.5m.so.1.0
>>>>> #19 0x00007ffff7a325f1 in PyEval_EvalFrameEx () from
>>>>> /usr/lib/libpython3.5m.so.1.0
>>>>> #20 0x00007ffff7a339e2 in ?? () from /usr/lib/libpython3.5m.so.1.0
>>>>> #21 0x00007ffff7a33ac3 in PyEval_EvalCodeEx () from
>>>>> /usr/lib/libpython3.5m.so.1.0
>>>>> #22 0x00007ffff799db98 in ?? () from /usr/lib/libpython3.5m.so.1.0
>>>>> #23 0x00007ffff79730da in PyObject_Call () from
>>>>> /usr/lib/libpython3.5m.so.1.0
>>>>> #24 0x00007ffff7989d64 in ?? () from /usr/lib/libpython3.5m.so.1.0
>>>>> #25 0x00007ffff79730da in PyObject_Call () from
>>>>> /usr/lib/libpython3.5m.so.1.0
>>>>> #26 0x00007ffff79cfa10 in ?? () from /usr/lib/libpython3.5m.so.1.0
>>>>> #27 0x00007ffff79cdde6 in ?? () from /usr/lib/libpython3.5m.so.1.0
>>>>> #28 0x00007ffff79730da in PyObject_Call () from
>>>>> /usr/lib/libpython3.5m.so.1.0
>>>>> #29 0x00007ffff7a2c4bc in PyEval_EvalFrameEx () from
>>>>> /usr/lib/libpython3.5m.so.1.0
>>>>> #30 0x00007ffff7a32942 in PyEval_EvalFrameEx () from
>>>>> /usr/lib/libpython3.5m.so.1.0
>>>>> #31 0x00007ffff7a339e2 in ?? () from /usr/lib/libpython3.5m.so.1.0
>>>>> #32 0x00007ffff7a33ac3 in PyEval_EvalCodeEx () from
>>>>> /usr/lib/libpython3.5m.so.1.0
>>>>> #33 0x00007ffff7a33aeb in PyEval_EvalCode () from
>>>>> /usr/lib/libpython3.5m.so.1.0
>>>>> #34 0x00007ffff7a2802d in ?? () from /usr/lib/libpython3.5m.so.1.0
>>>>> #35 0x00007ffff79ba5e9 in PyCFunction_Call () from
>>>>> /usr/lib/libpython3.5m.so.1.0
>>>>> #36 0x00007ffff7a325f1 in PyEval_EvalFrameEx () from
>>>>> /usr/lib/libpython3.5m.so.1.0
>>>>> #37 0x00007ffff7a339e2 in ?? () from /usr/lib/libpython3.5m.so.1.0
>>>>> #38 0x00007ffff7a306e0 in PyEval_EvalFrameEx () from
>>>>> /usr/lib/libpython3.5m.so.1.0
>>>>> #39 0x00007ffff7a339e2 in ?? () from /usr/lib/libpython3.5m.so.1.0
>>>>> #40 0x00007ffff7a33ac3 in PyEval_EvalCodeEx () from
>>>>> /usr/lib/libpython3.5m.so.1.0
>>>>> #41 0x00007ffff799db98 in ?? () from /usr/lib/libpython3.5m.so.1.0
>>>>> #42 0x00007ffff79730da in PyObject_Call () from
>>>>> /usr/lib/libpython3.5m.so.1.0
>>>>> #43 0x00007ffff7a6af01 in ?? () from /usr/lib/libpython3.5m.so.1.0
>>>>> #44 0x00007ffff7a6b7dc in Py_Main () from /usr/lib/libpython3.5m.so.1.0
>>>>> #45 0x0000000000400ae7 in main ()
>>>>> (gdb)
>>>>>
>>>>> Sorry for the lack of debugging symbols, but before I recompile VTK
>>>>> with debugging symbols, I thought I'd ask if anyone has an idea what may be
>>>>> the reason for the crash? I haven't seen any adverse effects from not
>>>>> calling this function, but I suspect something is broken? (how can I test?)
>>>>>
>>>>> 2. I can't seem to find a way to properly implement the
>>>>> WindowIsCurrentEvent, WindowIsDirectEvent and WindowSupportsOpenGLEvent
>>>>> render window events. E.g. (from below):
>>>>>
>>>>>     def _onWindowIsCurrentEvent(self, sender, event, callData):
>>>>>         callData = True  # FIXME: This won't work...
>>>>>
>>>>>     def _onWindowIsDirectEvent(self, sender, event, callData):
>>>>>         callData = True  # FIXME: This won't work...
>>>>>
>>>>>     def _onWindowSupportsOpenGLEvent(self, sender, event, callData):
>>>>>         callData = True  # FIXME: This won't work...
>>>>>
>>>>> The callData is a bool* and the handler is expected to write a bool to
>>>>> the pointed memory. I can't see that there's any way to do this from Python
>>>>> (is it possible with ctypes somehow?).
>>>>>
>>>>> So far I haven't seen any adverse effects from not implementing these
>>>>> three events correctly, but expect something to be broken..?
>>>>>
>>>>> Thankful for any advice on these two issues, and it would be great if
>>>>> someone could try out the example, with the
>>>>>
>>>>>     # self.renderWindow.OpenGLInitState()  # FIXME: Segfaults :(
>>>>>
>>>>> line uncommented, to confirm the segfault I'm seeing.
>>>>>
>>>>> Cheers,
>>>>> Elvis
>>>>>
>>>>>
>>>>> from PyQt5.QtCore import Qt, QTimer, QEvent, QSize
>>>>> from PyQt5.QtGui import QSurfaceFormat
>>>>> from PyQt5.QtWidgets import QWidget, QOpenGLWidget
>>>>>
>>>>> from vtk import vtkGenericOpenGLRenderWindow
>>>>> from vtk import vtkGenericRenderWindowInteractor
>>>>> from vtk import vtkCommand
>>>>> from vtk import vtkRenderer
>>>>>
>>>>> from vtk import VTK_CURSOR_DEFAULT, VTK_CURSOR_ARROW, VTK_CURSOR_SIZENE
>>>>> from vtk import VTK_CURSOR_SIZENW, VTK_CURSOR_SIZESW, VTK_CURSOR_SIZESE
>>>>> from vtk import VTK_CURSOR_SIZENS, VTK_CURSOR_SIZEWE,
>>>>> VTK_CURSOR_SIZEALL
>>>>> from vtk import VTK_CURSOR_HAND, VTK_CURSOR_CROSSHAIR
>>>>>
>>>>>
>>>>> class VTKWidget(QOpenGLWidget):
>>>>>
>>>>>     def __init__(self, surfaceFormat=QSurfaceFormat.defaultFormat(),
>>>>> *args, **kwargs):
>>>>>         super().__init__(*args, **kwargs)
>>>>>
>>>>>         # Request OpenGL 3.2 compatibility profile and enable
>>>>> multi-sampling
>>>>>         surfaceFormat.setMajorVersion(3)
>>>>>         surfaceFormat.setMinorVersion(2)
>>>>>         surfaceFormat.setProfile(QSurfaceFormat.CompatibilityProfile)
>>>>>         surfaceFormat.setSamples(8)
>>>>>         self.setFormat(surfaceFormat)
>>>>>
>>>>>         # Create render window
>>>>>         self.renderWindow = vtkGenericOpenGLRenderWindow()
>>>>>         self.renderWindow.SetSize(self.width(), self.height())
>>>>>         self.renderWindow.SetPosition(self.x(), self.y())
>>>>>
>>>>>         self.renderWindow.AddObserver(vtkCommand.StartEvent,
>>>>>                                       self._onStartEvent)
>>>>>         self.renderWindow.AddObserver(vtkCommand.EndEvent,
>>>>>                                       self._onEndEvent)
>>>>>         self.renderWindow.AddObserver(vtkCommand.CursorChangedEvent,
>>>>>                                       self._onCursorChangedEvent)
>>>>>
>>>>> self.renderWindow.AddObserver(vtkCommand.WindowMakeCurrentEvent,
>>>>>                                       self._onWindowMakeCurrentEvent)
>>>>>         self.renderWindow.AddObserver(vtkCommand.WindowIsCurrentEvent,
>>>>>                                       self._onWindowIsCurrentEvent)
>>>>>         self.renderWindow.AddObserver(vtkCommand.WindowFrameEvent,
>>>>>                                       self._onWindowFrameEvent)
>>>>>         self.renderWindow.AddObserver(vtkCommand.WindowIsDirectEvent,
>>>>>                                       self._onWindowIsDirectEvent)
>>>>>
>>>>> self.renderWindow.AddObserver(vtkCommand.WindowSupportsOpenGLEvent,
>>>>>
>>>>> self._onWindowSupportsOpenGLEvent)
>>>>>
>>>>>         # Create interactor
>>>>>         self.interactor = vtkGenericRenderWindowInteractor()
>>>>>         self.interactor.SetRenderWindow(self.renderWindow)
>>>>>         self.interactor.SetSize(self.width(), self.height())
>>>>>         self.interactor.AddObserver(vtkCommand.CreateTimerEvent,
>>>>>                                     lambda *_: self._timer.start(10))
>>>>>         self.interactor.AddObserver(vtkCommand.DestroyTimerEvent,
>>>>>                                     lambda *_: self._timer.stop())
>>>>>         self.interactor.Start()
>>>>>
>>>>>         # Create renderer
>>>>>         self.renderer = vtkRenderer()
>>>>>         self.renderWindow.AddRenderer(self.renderer)
>>>>>
>>>>>         # Timer for the interactor
>>>>>         self._timer = QTimer(self)
>>>>>         self._timer.timeout.connect(self.interactor.TimerEvent)
>>>>>
>>>>>         # Some tracked input state
>>>>>         self._pressedButton = Qt.NoButton
>>>>>         self._lastMouseX = 0
>>>>>         self._lastMouseY = 0
>>>>>         self._lastModifiers = Qt.NoModifier
>>>>>         self._lastButtons = Qt.NoButton
>>>>>         self._wheelDelta = 0
>>>>>
>>>>>         # Finalize render window before we're destroyed
>>>>>         self._hidden = QWidget(self)
>>>>>         self._hidden.hide()
>>>>>         self._hidden.destroyed.connect(self.renderWindow.Finalize)
>>>>>
>>>>>     #
>>>>>     # Handle VTK render window events
>>>>>     #
>>>>>
>>>>>     def _onStartEvent(self, *_):
>>>>>         self.makeCurrent()
>>>>>         self.renderWindow.PushState()
>>>>>         # self.renderWindow.OpenGLInitState()  # FIXME: Segfaults :(
>>>>>
>>>>>     def _onEndEvent(self, *_):
>>>>>         self.renderWindow.PopState()
>>>>>
>>>>>     def _onWindowMakeCurrentEvent(self, *_):
>>>>>         pass  # Handled automatically by QOpenGLWidget
>>>>>
>>>>>     def _onWindowIsCurrentEvent(self, sender, event, callData):
>>>>>         callData = True  # FIXME: This won't work...
>>>>>
>>>>>     def _onWindowIsDirectEvent(self, sender, event, callData):
>>>>>         callData = True  # FIXME: This won't work...
>>>>>
>>>>>     def _onWindowSupportsOpenGLEvent(self, sender, event, callData):
>>>>>         callData = True  # FIXME: This won't work...
>>>>>
>>>>>     def _onWindowFrameEvent(self, *_):
>>>>>         if self.renderWindow.GetSwapBuffers():
>>>>>             self.update()
>>>>>
>>>>>     def _onCursorChangedEvent(self):
>>>>>
>>>>>         def showCursor():
>>>>>             vtkCursor = self.renderWindow.GetCurrentCursor()
>>>>>             qtCursor = VTKWidget._cursors.get(vtkCursor,
>>>>> Qt.ArrowCursor)
>>>>>             self.setCursor(qtCursor)
>>>>>
>>>>>         # Defer until cursor has actually changed
>>>>>         QTimer.singleShot(0, showCursor)
>>>>>
>>>>>     #
>>>>>     # Implement QOpenGLWidget functions
>>>>>     #
>>>>>
>>>>>     def initializeGL(self):
>>>>>         self.renderWindow.OpenGLInitContext()
>>>>>
>>>>>     def paintGL(self):
>>>>>         self.interactor.Render()
>>>>>
>>>>>     def resizeGL(self, width, height):
>>>>>         self.renderWindow.SetSize(width, height)
>>>>>         self.interactor.SetSize(width, height)
>>>>>         self.interactor.ConfigureEvent()
>>>>>
>>>>>     #
>>>>>     # Handle QWidget events
>>>>>     #
>>>>>
>>>>>     def closeEvent(self, _):
>>>>>         self.renderWindow.Finalize()
>>>>>
>>>>>     def sizeHint(self):
>>>>>         return QSize(400, 400)
>>>>>
>>>>>     def moveEvent(self, event):
>>>>>         super().moveEvent(event)
>>>>>         self.renderWindow.SetPosition(self.x(), self.y())
>>>>>
>>>>>     def enterEvent(self, event):
>>>>>         ctrl, shift = self._modifiers(event)
>>>>>         self.interactor.SetEventInformationFlipY(self._lastMouseX,
>>>>> self._lastMouseY,
>>>>>                                                  ctrl, shift, chr(0),
>>>>> 0, None)
>>>>>         self.interactor.EnterEvent()
>>>>>
>>>>>     def leaveEvent(self, event):
>>>>>         ctrl, shift = self._modifiers(event)
>>>>>         self.interactor.SetEventInformationFlipY(self._lastMouseX,
>>>>> self._lastMouseY,
>>>>>                                                  ctrl, shift, chr(0),
>>>>> 0, None)
>>>>>         self.interactor.LeaveEvent()
>>>>>
>>>>>     def mousePressEvent(self, event):
>>>>>         ctrl, shift = self._modifiers(event)
>>>>>         repeat = 1 if event.type() == QEvent.MouseButtonDblClick else 0
>>>>>         self.interactor.SetEventInformationFlipY(event.x(), event.y(),
>>>>> ctrl, shift,
>>>>>                                                  chr(0), repeat, None)
>>>>>
>>>>>         self._pressedButton = event.button()
>>>>>
>>>>>         if self._pressedButton == Qt.LeftButton:
>>>>>             self.interactor.LeftButtonPressEvent()
>>>>>         elif self._pressedButton == Qt.RightButton:
>>>>>             self.interactor.RightButtonPressEvent()
>>>>>         elif self._pressedButton == Qt.MidButton:
>>>>>             self.interactor.MiddleButtonPressEvent()
>>>>>
>>>>>     def mouseReleaseEvent(self, event):
>>>>>         ctrl, shift = self._modifiers(event)
>>>>>         self.interactor.SetEventInformationFlipY(event.x(), event.y(),
>>>>> ctrl, shift,
>>>>>                                                  chr(0), 0, None)
>>>>>
>>>>>         if self._pressedButton == Qt.LeftButton:
>>>>>             self.interactor.LeftButtonReleaseEvent()
>>>>>         elif self._pressedButton == Qt.RightButton:
>>>>>             self.interactor.RightButtonReleaseEvent()
>>>>>         elif self._pressedButton == Qt.MidButton:
>>>>>             self.interactor.MiddleButtonReleaseEvent()
>>>>>
>>>>>         self._pressedButton = Qt.NoButton
>>>>>
>>>>>     def mouseMoveEvent(self, event):
>>>>>         self._lastModifiers = event.modifiers()
>>>>>         self._lastButtons = event.buttons()
>>>>>         self._lastMouseX = event.x()
>>>>>         self._lastMouseY = event.y()
>>>>>
>>>>>         ctrl, shift = self._modifiers(event)
>>>>>         self.interactor.SetEventInformationFlipY(event.x(), event.y(),
>>>>> ctrl, shift,
>>>>>                                                  chr(0), 0, None)
>>>>>         self.interactor.MouseMoveEvent()
>>>>>
>>>>>     def keyPressEvent(self, event):
>>>>>         ctrl, shift = self._modifiers(event)
>>>>>         key = str(event.text()) if event.key() < 256 else chr(0)
>>>>>         keySym = VTKWidget._qtKeyToKeySymbol(event.key())
>>>>>
>>>>>         if shift and len(keySym) == 1 and keySym.isalpha():
>>>>>             keySym = keySym.upper()
>>>>>
>>>>>         self.interactor.SetEventInformationFlipY(self._lastMouseX,
>>>>> self._lastMouseY,
>>>>>                                                  ctrl, shift, key, 0,
>>>>> keySym)
>>>>>         self.interactor.KeyPressEvent()
>>>>>         self.interactor.CharEvent()
>>>>>
>>>>>     def keyReleaseEvent(self, event):
>>>>>         ctrl, shift = self._modifiers(event)
>>>>>         key = chr(event.key()) if event.key() < 256 else chr(0)
>>>>>
>>>>>         self.interactor.SetEventInformationFlipY(self._lastMouseX,
>>>>> self._lastMouseY,
>>>>>                                                  ctrl, shift, key, 0,
>>>>> None)
>>>>>         self.interactor.KeyReleaseEvent()
>>>>>
>>>>>     def wheelEvent(self, event):
>>>>>         self._wheelDelta += event.angleDelta().y()
>>>>>
>>>>>         if self._wheelDelta >= 120:
>>>>>             self.interactor.MouseWheelForwardEvent()
>>>>>             self._wheelDelta = 0
>>>>>         elif self._wheelDelta <= -120:
>>>>>             self.interactor.MouseWheelBackwardEvent()
>>>>>             self._wheelDelta = 0
>>>>>
>>>>>     def _modifiers(self, event):
>>>>>         ctrl = shift = False
>>>>>
>>>>>         if hasattr(event, 'modifiers'):
>>>>>             if event.modifiers() & Qt.ShiftModifier:
>>>>>                 shift = True
>>>>>             if event.modifiers() & Qt.ControlModifier:
>>>>>                 ctrl = True
>>>>>         else:
>>>>>             if self._lastModifiers & Qt.ShiftModifier:
>>>>>                 shift = True
>>>>>             if self._lastModifiers & Qt.ControlModifier:
>>>>>                 ctrl = True
>>>>>
>>>>>         return ctrl, shift
>>>>>
>>>>>     @classmethod
>>>>>     def _qtKeyToKeySymbol(cls, key):
>>>>>         if key not in VTKWidget._keySymbols:
>>>>>             return None
>>>>>         return VTKWidget._keySymbols[key]
>>>>>
>>>>>     # Maps VTK cursors to Qt cursors
>>>>>     _cursors = {
>>>>>         VTK_CURSOR_DEFAULT: Qt.ArrowCursor,
>>>>>         VTK_CURSOR_ARROW: Qt.ArrowCursor,
>>>>>         VTK_CURSOR_SIZENE: Qt.SizeBDiagCursor,
>>>>>         VTK_CURSOR_SIZENW: Qt.SizeFDiagCursor,
>>>>>         VTK_CURSOR_SIZESW: Qt.SizeBDiagCursor,
>>>>>         VTK_CURSOR_SIZESE: Qt.SizeFDiagCursor,
>>>>>         VTK_CURSOR_SIZENS: Qt.SizeVerCursor,
>>>>>         VTK_CURSOR_SIZEWE: Qt.SizeHorCursor,
>>>>>         VTK_CURSOR_SIZEALL: Qt.SizeAllCursor,
>>>>>         VTK_CURSOR_HAND: Qt.PointingHandCursor,
>>>>>         VTK_CURSOR_CROSSHAIR: Qt.CrossCursor
>>>>>     }
>>>>>
>>>>>     # Maps Qt keys to VTK key symbols
>>>>>     _keySymbols = {
>>>>>         Qt.Key_Backspace: 'BackSpace',
>>>>>         Qt.Key_Tab: 'Tab',
>>>>>         Qt.Key_Backtab: 'Tab',
>>>>>         # Qt.Key_Clear : 'Clear',
>>>>>         Qt.Key_Return: 'Return',
>>>>>         Qt.Key_Enter: 'Return',
>>>>>         Qt.Key_Shift: 'Shift_L',
>>>>>         Qt.Key_Control: 'Control_L',
>>>>>         Qt.Key_Alt: 'Alt_L',
>>>>>         Qt.Key_Pause: 'Pause',
>>>>>         Qt.Key_CapsLock: 'Caps_Lock',
>>>>>         Qt.Key_Escape: 'Escape',
>>>>>         Qt.Key_Space: 'space',
>>>>>         # Qt.Key_Prior : 'Prior',
>>>>>         # Qt.Key_Next : 'Next',
>>>>>         Qt.Key_End: 'End',
>>>>>         Qt.Key_Home: 'Home',
>>>>>         Qt.Key_Left: 'Left',
>>>>>         Qt.Key_Up: 'Up',
>>>>>         Qt.Key_Right: 'Right',
>>>>>         Qt.Key_Down: 'Down',
>>>>>         Qt.Key_SysReq: 'Snapshot',
>>>>>         Qt.Key_Insert: 'Insert',
>>>>>         Qt.Key_Delete: 'Delete',
>>>>>         Qt.Key_Help: 'Help',
>>>>>         Qt.Key_0: '0',
>>>>>         Qt.Key_1: '1',
>>>>>         Qt.Key_2: '2',
>>>>>         Qt.Key_3: '3',
>>>>>         Qt.Key_4: '4',
>>>>>         Qt.Key_5: '5',
>>>>>         Qt.Key_6: '6',
>>>>>         Qt.Key_7: '7',
>>>>>         Qt.Key_8: '8',
>>>>>         Qt.Key_9: '9',
>>>>>         Qt.Key_A: 'a',
>>>>>         Qt.Key_B: 'b',
>>>>>         Qt.Key_C: 'c',
>>>>>         Qt.Key_D: 'd',
>>>>>         Qt.Key_E: 'e',
>>>>>         Qt.Key_F: 'f',
>>>>>         Qt.Key_G: 'g',
>>>>>         Qt.Key_H: 'h',
>>>>>         Qt.Key_I: 'i',
>>>>>         Qt.Key_J: 'j',
>>>>>         Qt.Key_K: 'k',
>>>>>         Qt.Key_L: 'l',
>>>>>         Qt.Key_M: 'm',
>>>>>         Qt.Key_N: 'n',
>>>>>         Qt.Key_O: 'o',
>>>>>         Qt.Key_P: 'p',
>>>>>         Qt.Key_Q: 'q',
>>>>>         Qt.Key_R: 'r',
>>>>>         Qt.Key_S: 's',
>>>>>         Qt.Key_T: 't',
>>>>>         Qt.Key_U: 'u',
>>>>>         Qt.Key_V: 'v',
>>>>>         Qt.Key_W: 'w',
>>>>>         Qt.Key_X: 'x',
>>>>>         Qt.Key_Y: 'y',
>>>>>         Qt.Key_Z: 'z',
>>>>>         Qt.Key_Asterisk: 'asterisk',
>>>>>         Qt.Key_Plus: 'plus',
>>>>>         Qt.Key_Minus: 'minus',
>>>>>         Qt.Key_Period: 'period',
>>>>>         Qt.Key_Slash: 'slash',
>>>>>         Qt.Key_F1: 'F1',
>>>>>         Qt.Key_F2: 'F2',
>>>>>         Qt.Key_F3: 'F3',
>>>>>         Qt.Key_F4: 'F4',
>>>>>         Qt.Key_F5: 'F5',
>>>>>         Qt.Key_F6: 'F6',
>>>>>         Qt.Key_F7: 'F7',
>>>>>         Qt.Key_F8: 'F8',
>>>>>         Qt.Key_F9: 'F9',
>>>>>         Qt.Key_F10: 'F10',
>>>>>         Qt.Key_F11: 'F11',
>>>>>         Qt.Key_F12: 'F12',
>>>>>         Qt.Key_F13: 'F13',
>>>>>         Qt.Key_F14: 'F14',
>>>>>         Qt.Key_F15: 'F15',
>>>>>         Qt.Key_F16: 'F16',
>>>>>         Qt.Key_F17: 'F17',
>>>>>         Qt.Key_F18: 'F18',
>>>>>         Qt.Key_F19: 'F19',
>>>>>         Qt.Key_F20: 'F20',
>>>>>         Qt.Key_F21: 'F21',
>>>>>         Qt.Key_F22: 'F22',
>>>>>         Qt.Key_F23: 'F23',
>>>>>         Qt.Key_F24: 'F24',
>>>>>         Qt.Key_NumLock: 'Num_Lock',
>>>>>         Qt.Key_ScrollLock: 'Scroll_Lock'
>>>>>     }
>>>>>
>>>>> def example():
>>>>>     #
>>>>>     # Try out VTKWidget by showing a couple of cones
>>>>>     #
>>>>>     from sys import argv, exit
>>>>>     from PyQt5.QtWidgets import QApplication, QVBoxLayout
>>>>>     from vtk import vtkConeSource, vtkPolyDataMapper, vtkActor
>>>>>
>>>>>     app = QApplication(argv)
>>>>>
>>>>>     layout = QVBoxLayout()
>>>>>
>>>>>     for i in range(2):
>>>>>         widget = VTKWidget()
>>>>>
>>>>>         coneSource = vtkConeSource()
>>>>>         coneSource.SetResolution(8)
>>>>>
>>>>>         coneMapper = vtkPolyDataMapper()
>>>>>         coneMapper.SetInputConnection(coneSource.GetOutputPort())
>>>>>
>>>>>         coneActor = vtkActor()
>>>>>         coneActor.SetMapper(coneMapper)
>>>>>
>>>>>         widget.renderer.AddActor(coneActor)
>>>>>
>>>>>         layout.addWidget(widget)
>>>>>
>>>>>     container = QWidget()
>>>>>     container.setLayout(layout)
>>>>>     container.show()
>>>>>
>>>>>     exit(app.exec_())
>>>>>
>>>>>
>>>>> if __name__ == '__main__':
>>>>>     example()
>>>>>
>>>>>
>>>>
>>>
>>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://public.kitware.com/pipermail/vtkusers/attachments/20160627/439c2c2e/attachment.html>


More information about the vtkusers mailing list