Embedding VTK in GTK Window by Using Python

I want to embed VTK object in GTK window. I want to draw a cylinder which is explained in this page. It is plotted in a seperate window. But I want to plot it in a GTK gui generated by Glade. I have a windows 10 x64 installed machine with python 3.8, GTK3 and VTK 8.2.

Here is an example but as i understand from the forum it does not work.

How it can be plotted?

I modified an example that exists in the vtk folders. I have modified it for gtk3. It gives error when vtkrenderwindow is packed by box. Events also do not work, but my first goal is to plot vtk embedded in gtk gui. Here is the code i modified:

import gi
gi.require_version('Gtk', '3.0')
from gi.repository import Gtk as gtk
from gi.repository import Gdk as GDK
from gi.repository import GObject
import vtk
from past.builtins import apply
from vtkmodules.vtkRenderingCore import vtkGenericRenderWindowInteractor
import math

class GtkVTKRenderWindowInteractor(gtk.GLArea):
    def __init__(self, *args):
        """l = list(args)
        attr = (GDK.RGBA, gtk.DOUBLEBUFFER)
        l.insert(0, self)
        l.insert(1, attr)
        apply(gtk.GLArea.__init__, l)"""
        self._RenderWindow = vtkRenderWindow()

        # private attributes
        self.__Created = 0
        self._ActiveButton = 0

        self._Iren = vtkGenericRenderWindowInteractor()
        self._Iren.SetRenderWindow(self._RenderWindow)

        self._Iren.AddObserver('CreateTimerEvent', self.CreateTimer)
        self._Iren.AddObserver('DestroyTimerEvent', self.DestroyTimer)
        self.ConnectSignals()

        # need this to be able to handle key_press events.
        self.set_flags(gtk.CAN_FOCUS)
        # default size
        self.set_usize(300, 300)

    def set_usize(self, w, h):
        gtkgl.GtkGLArea.set_usize(self, w, h)
        self._RenderWindow.SetSize(w, h)
        self._Iren.SetSize(w, h)
        self._Iren.ConfigureEvent()

    def ConnectSignals(self):
        self.connect("realize", self.OnRealize)
        self.connect("expose_event", self.OnExpose)
        self.connect("configure_event", self.OnConfigure)
        self.connect("button_press_event", self.OnButtonDown)
        self.connect("button_release_event", self.OnButtonUp)
        self.connect("motion_notify_event", self.OnMouseMove)
        self.connect("enter_notify_event", self.OnEnter)
        self.connect("leave_notify_event", self.OnLeave)
        self.connect("key_press_event", self.OnKeyPress)
        self.connect("delete_event", self.OnDestroy)
        self.add_events(GDK.EXPOSURE_MASK| GDK.BUTTON_PRESS_MASK |
                        GDK.BUTTON_RELEASE_MASK |
                        GDK.KEY_PRESS_MASK |
                        GDK.POINTER_MOTION_MASK |
                        GDK.POINTER_MOTION_HINT_MASK |
                        GDK.ENTER_NOTIFY_MASK | GDK.LEAVE_NOTIFY_MASK)

    def __getattr__(self, attr):
        """Makes the object behave like a
        vtkGenericRenderWindowInteractor"""
        if attr == '__vtk__':
            return lambda t=self._Iren: t
        elif hasattr(self._Iren, attr):
            return getattr(self._Iren, attr)
        else:
            raise AttributeError(self.__class__.__name__ +
                  " has no attribute named " + attr)

    def CreateTimer(self, obj, event):
        gtk.timeout_add(10, self._Iren.TimerEvent)

    def DestroyTimer(self, obj, event):
        """The timer is a one shot timer so will expire automatically."""
        return 1

    def GetRenderWindow(self):
        return self._RenderWindow

    def Render(self):
        if self.__Created:
            self._RenderWindow.Render()

    def OnRealize(self, *args):
        if self.__Created == 0:
            # you can't get the xid without the window being realized.
            self.realize()
            win_id = str(self.get_window().xid)
            self._RenderWindow.SetWindowInfo(win_id)
            self._Iren.Initialize()
            self.__Created = 1
        return gtk.TRUE

    def OnConfigure(self, wid, event=None):
        sz = self._RenderWindow.GetSize()
        if (event.width != sz[0]) or (event.height != sz[1]):
            self._Iren.SetSize(event.width, event.height)
            self._Iren.ConfigureEvent()
        return gtk.TRUE

    def OnExpose(self, *args):
        self.Render()
        return gtk.TRUE

    def OnDestroy(self, event=None):
        self.hide()
        del self._RenderWindow
        self.destroy()
        return gtk.TRUE

    def _GetCtrlShift(self, event):
        ctrl, shift = 0, 0
        if ((event.state & GDK.CONTROL_MASK) == GDK.CONTROL_MASK):
            ctrl = 1
        if ((event.state & GDK.SHIFT_MASK) == GDK.SHIFT_MASK):
            shift = 1
        return ctrl, shift

    def OnButtonDown(self, wid, event):
        """Mouse button pressed."""
        m = self.get_pointer()
        ctrl, shift = self._GetCtrlShift(event)
        self._Iren.SetEventInformationFlipY(m[0], m[1], ctrl, shift,
                                            chr(0), 0, None)
        button = event.button
        if button == 3:
            self._Iren.RightButtonPressEvent()
            return gtk.TRUE
        elif button == 1:
            self._Iren.LeftButtonPressEvent()
            return gtk.TRUE
        elif button == 2:
            self._Iren.MiddleButtonPressEvent()
            return gtk.TRUE
        else:
            return gtk.FALSE

    def OnButtonUp(self, wid, event):
        """Mouse button released."""
        m = self.get_pointer()
        ctrl, shift = self._GetCtrlShift(event)
        self._Iren.SetEventInformationFlipY(m[0], m[1], ctrl, shift,
                                            chr(0), 0, None)
        button = event.button
        if button == 3:
            self._Iren.RightButtonReleaseEvent()
            return gtk.TRUE
        elif button == 1:
            self._Iren.LeftButtonReleaseEvent()
            return gtk.TRUE
        elif button == 2:
            self._Iren.MiddleButtonReleaseEvent()
            return gtk.TRUE

        return gtk.FALSE

    def OnMouseMove(self, wid, event):
        """Mouse has moved."""
        m = self.get_pointer()
        ctrl, shift = self._GetCtrlShift(event)
        self._Iren.SetEventInformationFlipY(m[0], m[1], ctrl, shift,
                                            chr(0), 0, None)
        self._Iren.MouseMoveEvent()
        return gtk.TRUE

    def OnEnter(self, wid, event):
        """Entering the vtkRenderWindow."""
        self.grab_focus()
        m = self.get_pointer()
        ctrl, shift = self._GetCtrlShift(event)
        self._Iren.SetEventInformationFlipY(m[0], m[1], ctrl, shift,
                                            chr(0), 0, None)
        self._Iren.EnterEvent()
        return gtk.TRUE

    def OnLeave(self, wid, event):
        """Leaving the vtkRenderWindow."""
        m = self.get_pointer()
        ctrl, shift = self._GetCtrlShift(event)
        self._Iren.SetEventInformationFlipY(m[0], m[1], ctrl, shift,
                                            chr(0), 0, None)
        self._Iren.LeaveEvent()
        return gtk.TRUE

    def OnKeyPress(self, wid, event):
        """Key pressed."""
        m = self.get_pointer()
        ctrl, shift = self._GetCtrlShift(event)
        keycode, keysym = event.keyval, event.string
        key = chr(0)
        if keycode < 256:
            key = chr(keycode)
        self._Iren.SetEventInformationFlipY(m[0], m[1], ctrl, shift,
                                            key, 0, keysym)
        self._Iren.KeyPressEvent()
        self._Iren.CharEvent()
        return gtk.TRUE

    def OnKeyRelease(self, wid, event):
        "Key released."
        m = self.get_pointer()
        ctrl, shift = self._GetCtrlShift(event)
        keycode, keysym = event.keyval, event.string
        key = chr(0)
        if keycode < 256:
            key = chr(keycode)
        self._Iren.SetEventInformationFlipY(m[0], m[1], ctrl, shift,
                                            key, 0, keysym)
        self._Iren.KeyReleaseEvent()
        return gtk.TRUE

    def Initialize(self):
        if self.__Created:
            self._Iren.Initialize()


def main():
    from vtkmodules.vtkFiltersSources import vtkConeSource
    from vtkmodules.vtkRenderingCore import vtkActor, vtkPolyDataMapper, vtkRenderer

    # The main window
    window = gtk.Window()
    window.set_title("A GtkVTKRenderWindow Demo!")
    window.connect("destroy", gtk.main_quit)
    window.connect("delete_event", gtk.main_quit)
    window.set_border_width(10)

    # A VBox into which widgets are packed.
    vbox = gtk.Box(spacing=3)
    window.add(vbox)
    vbox.show()

    # The GtkVTKRenderWindow
    gvtk = vtk.vtkRenderWindow()
    # gvtk.SetDesiredUpdateRate(1000)
    gvtk.SetSize(400, 400)
    vbox.pack_start(gvtk, True, True, 0)
    gvtk.Render()

    vbox.show
    #gvtk.show()
    gvtk.Initialize()
    gvtk.Start()
    # prevents 'q' from exiting the app.
    gvtk.AddObserver("ExitEvent", lambda o,e,x=None: x)

    # The VTK stuff.
    cone = vtkConeSource()
    cone.SetResolution(80)
    coneMapper = vtkPolyDataMapper()
    coneMapper.SetInputConnection(cone.GetOutputPort())
    #coneActor = vtkLODActor()
    coneActor = vtkActor()
    coneActor.SetMapper(coneMapper)
    coneActor.GetProperty().SetColor(0.5, 0.5, 1.0)
    ren = vtkRenderer()
    # gvtk.GetRenderWindow().AddRenderer(ren)
    gvtk.AddRenderer(ren)
    ren.AddActor(coneActor)

    # show the main window and start event processing.
    #window.show()
    window.show_all()
    gtk.main()


if __name__ == "__main__":
    main()