[vtkusers] Using context views in a QVTKRenderWindowInteractor from Python

Elvis Stansvik elvis.stansvik at orexplore.com
Wed Jun 15 07:35:37 EDT 2016


2016-05-23 17:28 GMT+02:00 Elvis Stansvik <elvis.stansvik at orexplore.com>:

> 2016-05-23 16:55 GMT+02:00 Elvis Stansvik <elvis.stansvik at orexplore.com>:
>
>> 2016-05-23 16:28 GMT+02:00 Elvis Stansvik <elvis.stansvik at orexplore.com>:
>>
>>> I'm trying to use a context view (my goal is to show an XYChart) inside
>>> a QVTKRenderWindowInteractor, but I'm struggling to get the initialization
>>> of render window / interactor right.
>>>
>>> The docs for vtkRenderViewBase (base class for vtkContextView) says:
>>>
>>> "In order to use the view with a QVTKWidget the following code is
>>> required to ensure the interactor and render window are initialized
>>> properly.
>>>
>>> QVTKWidget *widget = new QVTKWidget;
>>> vtkContextView *view = vtkContextView::New();
>>> view->SetInteractor(widget->GetInteractor());
>>> widget->SetRenderWindow(view->GetRenderWindow());"
>>>
>>> but this is about QVTKWidget, the C++ widget class, which is quite
>>> different from the Python QVTKRenderWindowInteractor class.
>>>
>>> My failed attempt to recreate this initialization sequence when using
>>> QVTKRenderWindowInteractor is this:
>>>
>>>
>>> class TestWidget(QVTKRenderWindowInteractor):
>>>
>>>     def __init__(self, parent=None):
>>>
>>>         # We need a render window and interactor to pass to
>>>         # QVTKRenderWindowInteractor constructor.
>>>         self.renderWindow = vtkRenderWindow()
>>>         self.interactor = vtkGenericRenderWindowInteractor()
>>>         self.interactor.SetRenderWindow(self.renderWindow)
>>>
>>>         super(TestWidget, self).__init__(
>>>             parent, rw=self.renderWindow, iren=self.interactor)
>>>
>>>         # Create a context view and set it to use the same
>>>         # interactor as the QVTKRenderWindowInteractor.
>>>         self.contextView = vtkContextView()
>>>         self.contextView.SetInteractor(self.interactor)
>>>
>>>         # Create chart and add it to the scene of the context view.
>>>         self.chart = vtkChartXY()
>>>         self.contextView.GetScene().AddItem(self.chart)
>>>
>>>         # Initialize and start.
>>>         self.Initialize()
>>>         self.Start()
>>>
>>>
>>> if __name__ == '__main__':
>>>
>>>     app = QApplication(argv)
>>>
>>>     widget = TestWidget()
>>>     widget.show()
>>>
>>>     exit(app.exec_())
>>>
>>>
>>> But something goes wrong here, because two windows show up (see attached
>>> screenshot). The application also segfaults on exit. Besides, it looks very
>>> kludgy to have to do stuff before the call to super() here. Is this really
>>> the right way to use the API?
>>>
>>> If anyone has worked with QVTKRenderWindowInteractor and vtkContextView,
>>> I'd much appriciate some advice.
>>>
>>
>> Inspired by an older post on this subject [1], I was able to get it
>> partly working with:
>>
>> class TestWidget(QVTKRenderWindowInteractor):
>>
>>     def __init__(self, parent=None):
>>         super(TestWidget, self).__init__(parent)
>>
>>         self.contextView = vtkContextView()
>>         self.chart = vtkChartXY()
>>         self.contextView.GetScene().AddItem(self.chart)
>>
>>         # Add renderer of context view to the render window of the widget.
>>         self.GetRenderWindow().AddRenderer(self.contextView.GetRenderer())
>>
>>         self.Initialize()
>>         self.Start()
>>
>> The chart is empty here, but I've verified by adding some items to it
>> that it at least shows up correctly, in a single window.
>>
>> The problem is that interaction of course doesn't work, and if I also add
>>
>>         self.contextView.SetInteractor(self._Iren)
>>
>> to set the interactor of the context view to the
>> vtkGenericRenderWindowInteractor backing the QVTKRenderWindowInteractor,
>> I'm back to the problem with two windows showing up.
>>
>> I need interaction to work, because my goal is to show an opacity
>> function editor item in the chart.
>>
>> Thankful for any and all advice!
>>
>
> To better illustrate, here's the scatter plot Python example from the
> wiki, with the code I've added to try to make it work with
> QVTKRenderWindowInteractor.
>
> The result is that when the application is executed, a "Visualization
> Toolkit - OpenGL" window first shows up, where interaction works fine. This
> is not the Qt window though. The Qt window shows up if I close the first
> window, and interaction does not work (try hovering the data points).
>
> How would this example need to be modified for it to work? (chart shown in
> the Qt window, with interaction working).
>
> Best regards,
> Elvis
>
> # <ADDED>
> app = QApplication(sys.argv)
>
> widget = QVTKRenderWindowInteractor()
> widget.Initialize()
> widget.Start()
> # </ADDED>
>
> view = vtk.vtkContextView()
> view.GetRenderer().SetBackground(1.0, 1.0, 1.0)
> view.GetRenderWindow().SetSize(400, 300)
>
> chart = vtk.vtkChartXY()
> view.GetScene().AddItem(chart)
> chart.SetShowLegend(True)
>
> table = vtk.vtkTable()
>
> arrX = vtk.vtkFloatArray()
> arrX.SetName('X Axis')
>
> arrC = vtk.vtkFloatArray()
> arrC.SetName('Cosine')
>
> arrS = vtk.vtkFloatArray()
> arrS.SetName('Sine')
>
> arrT = vtk.vtkFloatArray()
> arrT.SetName('Sine-Cosine')
>
> table.AddColumn(arrC)
> table.AddColumn(arrS)
> table.AddColumn(arrX)
> table.AddColumn(arrT)
>
> numPoints = 40
>
> inc = 7.5 / (numPoints - 1)
> table.SetNumberOfRows(numPoints)
> for i in range(numPoints):
>     table.SetValue(i, 0, i * inc)
>     table.SetValue(i, 1, math.cos(i * inc))
>     table.SetValue(i, 2, math.sin(i * inc))
>     table.SetValue(i, 3, math.sin(i * inc) - math.cos(i * inc))
>
> points = chart.AddPlot(vtk.vtkChart.POINTS)
> points.SetInputData(table, 0, 1)
> points.SetColor(0, 0, 0, 255)
> points.SetWidth(1.0)
> points.SetMarkerStyle(vtk.vtkPlotPoints.CROSS)
>
> points = chart.AddPlot(vtk.vtkChart.POINTS)
> points.SetInputData(table, 0, 2)
> points.SetColor(0, 0, 0, 255)
> points.SetWidth(1.0)
> points.SetMarkerStyle(vtk.vtkPlotPoints.PLUS)
>
> points = chart.AddPlot(vtk.vtkChart.POINTS)
> points.SetInputData(table, 0, 3)
> points.SetColor(0, 0, 255, 255)
> points.SetWidth(1.0)
> points.SetMarkerStyle(vtk.vtkPlotPoints.CIRCLE)
>
> view.GetRenderWindow().SetMultiSamples(0)
> view.GetInteractor().Initialize()
> view.GetInteractor().Start()
>
> # <ADDED>
> widget.GetRenderWindow().AddRenderer(view.GetRenderer())
> widget.setWindowTitle('Qt Widget')
> widget.show()
>
> exit(app.exec_())
> # </ADDED>
>

I still haven't found a solution to the above :(

Does anyone have an example of how to use QVTKRenderWindowInteractor and
context views? Or know what might be happening in the above example?

My end goal is simply to be able to show a vtkChartXY in a Qt widget, for
the purpose of setting up color transfer function editors similar to those
in VolView/Paraview.

Elvis


>
>>
>> Elvis
>>
>> [1] http://www.vtk.org/pipermail/vtkusers/2011-July/068893.html
>>
>>
>>>
>>> Cheers,
>>> Elvis
>>>
>>>
>>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://public.kitware.com/pipermail/vtkusers/attachments/20160615/a7b6ce42/attachment.html>


More information about the vtkusers mailing list