Интеграция PyQt4 и vtk - X Error [решено]

Пишу программу на питоне с использованием PyQt4, нужно применить визуализацию, лучше всего подошла библиотека vtk. Когда пытаюсь приделать vtk к интерфейсу, возникает ошибка:

X Error: BadWindow (invalid Window parameter) 3
  Major opcode: 2 (X_ChangeWindowAttributes)
  Resource id:  0x5600013
X Error: BadWindow (invalid Window parameter) 3
  Major opcode: 3 (X_GetWindowAttributes)
  Resource id:  0x5600013

Вот виджет, который должен выводить 3D-модель.

# -*- coding: utf-8 -*-

from PyQt4.QtGui import *
from PyQt4.QtCore import *
from vtk import *
from vtk.qt4.QVTKRenderWindowInteractor import QVTKRenderWindowInteractor

class GLViewer(QFrame):
    def __init__(self, parent=None):
        QFrame.__init__(self, parent)
        iren = QVTKRenderWindowInteractor(self)
        iren.Initialize()
        iren.Start()
        renderer = vtkRenderer()
        iren.GetRenderWindow().AddRenderer(renderer)
        cube = vtkCubeSource()
        mapper = vtkPolyDataMapper()
        mapper.SetInput(cube.GetOutput())
        actor = vtkActor()
        actor.SetMapper(mapper)
        renderer.AddActor(actor)

Запускается и работает пример, который находится в vtk.qt4.QVTKRenderWindowInteractor, но в том случае QVTKRenderWindowInteractor() вызывается без параметров, то есть не имеет родительского виджета и сам формирует окно. Если я в своем случае вызываю QVTKRenderWindowInteractor() без параметров, то в его области ничего не отображается, если после этого вызвать его метод setParent(self), то он начинает отображать какой-то небольшой мусор или опять пустоту, и в консоль вылезают ошибки наподобие вышеописанных.

Версии: dev-python/PyQt4-4.4.4-r2 (пробовал 4.5, результат тот же), sci-libs/vtk-5.2.0-r1, x11-base/xorg-server-1.6.1.901-r3 (пробовал 1.5.3-r6, результат тот же), x11-libs/qt-4.5.1

Помогите их подружить.

.

Давайте по шагам:
У меня вот это создаёт вращающийся красный куб

import os, vtk
cube = vtk.vtkCubeSource()
cube.SetXLength(10);cube.SetYLength(10);cube.SetZLength(10);cube.SetCenter(1,2,3)
mapper = vtk.vtkPolyDataMapper()
mapper.SetInput(cube.GetOutput())
actor = vtk.vtkActor()
actor.SetMapper(mapper);actor.GetProperty().SetColor(1,0,0)
ren = vtk.vtkRenderer()
ren.AddActor(actor)
renWin = vtk.vtkRenderWindow()
renWin.AddRenderer(ren)
iren = vtk.vtkRenderWindowInteractor()
iren.SetRenderWindow(renWin)
renWin.SetSize(450,450)
iren.Initialize()
iren.Start()

А у вас?

Однако попытка заменить "iren = vtk.vtkRenderWindowInteractor()" на

from vtk.qt4.QVTKRenderWindowInteractor import QVTKRenderWindowInteractor
iren = QVTKRenderWindowInteractor()

даёт ошибку QWidget: Must construct a QApplication before a QPaintDevice

Дайте более полный код для тестирования с описанием желаемого, но ненаблюдаемого у вас результата

Это подпись, которую невозможно истолковать неправильно

Вот сделал пример

Вот сделал пример самостоятельного приложения.

В этом случае QVTKRenderWindowInteractor создается дочерним элементом виджета window. При запуске выходят вышеописанные ошибки.

# -*- coding: utf-8 -*-

import sys
from PyQt4.QtGui import *
from PyQt4.QtCore import *
from vtk import *
from vtk.qt4.QVTKRenderWindowInteractor import QVTKRenderWindowInteractor

if __name__ == '__main__':
    app = QApplication(sys.argv)
    window = QWidget()
    
    iren = QVTKRenderWindowInteractor(window)
    iren.Initialize()
    iren.Start()
    renderer = vtkRenderer()
    iren.GetRenderWindow().AddRenderer(renderer)
    cube = vtkCubeSource()
    mapper = vtkPolyDataMapper()
    mapper.SetInput(cube.GetOutput())
    actor = vtkActor()
    actor.SetMapper(mapper)
    renderer.AddActor(actor)
    
    window.show()
    sys.exit(app.exec_())

А вот здесь QVTKRenderWindowInteractor не имеет родителя, тогда все работает.

# -*- coding: utf-8 -*-

import sys
from PyQt4.QtGui import *
from PyQt4.QtCore import *
from vtk import *
from vtk.qt4.QVTKRenderWindowInteractor import QVTKRenderWindowInteractor

if __name__ == '__main__':
    app = QApplication(sys.argv)
    
    iren = QVTKRenderWindowInteractor()
    iren.Initialize()
    iren.Start()
    renderer = vtkRenderer()
    iren.GetRenderWindow().AddRenderer(renderer)
    cube = vtkCubeSource()
    mapper = vtkPolyDataMapper()
    mapper.SetInput(cube.GetOutput())
    actor = vtkActor()
    actor.SetMapper(mapper)
    renderer.AddActor(actor)
    
    iren.show()
    sys.exit(app.exec_())

Мне необходимо использовать первый вариант, чтобы встроить QVTKRenderWindowInteractor в интерфейс программы.

.

Хак для встраивания (я не перепроверял) http://www.vtk.org/pipermail/vtkusers/2009-May/101042.html

Это подпись, которую невозможно истолковать неправильно

Спасибо за помощь, но по той

Спасибо за помощь, но по той ссылке не совсем моя проблема. Свою я решил просто убрав вызов iren.Initialize(). Я так и не понял зачем он нужен (и даже откуда он унаследован, в классах QVTKRenderWindowInteractor, QWidget и QObject ничего подобного нет), как и следующий за ним iren.Start(), пока что все работает без них и без ошибок, надеюсь потом не вылезет боком.
А вот потом случилось то, о чем пишут по ссылке, виджет не хотел правильно масштабироваться, это решилось переопределением метода родительского виджета:

    def resizeEvent(self, event):
        if event.size() != event.oldSize():
            self.iren.resize(event.size())

что гораздо проще, чем способ, предложенный там.

Проблема решена, надеюсь, что не до встречи с подводным камнем.

.

Из документации к потомкам vtkRenderWindowInteractor следует, что Initialize + Start ... is good for when you don't have a user interface, but you still want to have mouse interaction. Start() will start up the X event loop and never return.
Так как Qt предлагает свой event loop, думается, никаких подводных камней не будет.
Когда же Qt нет (как в моём коде с красным кубом), отстутствие Initialize и Start приводит к немедленному завершению программы.

Это подпись, которую невозможно истолковать неправильно

Настройки просмотра комментариев

Выберите нужный метод показа комментариев и нажмите "Сохранить установки".