Hello all,
I have a PyQt application with a QMainWindow that opens a subwindow/QWidget. The subwindow contains a QVTKRenderWindowInteractor widget. I want to be able to call the subwindow, close it, and then re-open it again as needed. However, if the window is closed using the close/X button, the QVTK Widget no longer renders. If the window is instead closed by calling the close()
method, the QVTK Widget still works. The code below replicates the issue.
Why does this occur? What does Qt or VTK do differently between closing the window with “X” button and calling .close()?
Is there a way to restart the QVTK widget after closing? Or is it actually better practice to just create another instance with each button press and closure?
Thanks.
import os, sys
from PyQt5 import QtGui, QtWidgets, QtCore
import vtk
from vtkmodules.qt.QVTKRenderWindowInteractor import QVTKRenderWindowInteractor
#%% Parameters
wd = '...'
filename = '...'
#%% Defined functions and classes
def read_vtp(filepath):
reader = vtk.vtkXMLPolyDataReader()
reader.SetFileName(filepath)
reader.Update()
return reader.GetOutput()
class ViewSurface(QtWidgets.QWidget):
def __init__(self, surface):
super().__init__()
self.resize(1000, 1000)
self.Layout = QtWidgets.QVBoxLayout()
self.setLayout(self.Layout)
self.Surface = surface
self.Mapper = vtk.vtkPolyDataMapper()
self.Mapper.SetInputData(self.Surface)
self.Actor = vtk.vtkActor()
self.Actor.SetMapper(self.Mapper)
self.QVTKRWI = QVTKRenderWindowInteractor(parent=self)
self.Layout.addWidget(self.QVTKRWI)
self.Renderer = vtk.vtkRenderer()
self.Renderer.AddActor(self.Actor)
self.RenderWindow = self.QVTKRWI.GetRenderWindow()
self.RenderWindow.AddRenderer(self.Renderer)
self.Interactor = self.RenderWindow.GetInteractor()
self.Interactor.GetInteractorStyle().SetCurrentStyleToTrackballCamera()
self.CloseButton = QtWidgets.QPushButton(text='Close')
self.Layout.addWidget(self.CloseButton)
self.CloseButton.clicked.connect(self.close)
def Show(self):
self.show()
self.Interactor.Initialize()
self.RenderWindow.Render()
class MainWindow(QtWidgets.QMainWindow):
def __init__(self):
super().__init__()
self.PushButton = QtWidgets.QPushButton(text='Open Widget')
self.setCentralWidget(self.PushButton)
self.PushButton.clicked.connect(self.OpenWidget)
self.Surface = None
self.ViewSurface = None
def OpenWidget(self):
if not self.ViewSurface:
self.ViewSurface = ViewSurface(self.Surface)
self.ViewSurface.Show()
#%% Script
filepath = os.path.join(wd, filename)
surface = read_vtp(filepath)
app = QtWidgets.QApplication(sys.argv)
window = MainWindow()
window.Surface = surface
window.show()
app.exec()
The main window is a single button “Open Widget”:
Pressing the button calls a new window with a QVTK widget:
If the window is called using the Close button and the “Open Widget” button is pressed again, the QVTK widget appears normally. However, if the window is closed using the “X” button and “Open Widget” is pressed, the QVTK widget doesn’t render: