Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. QML and Qt Quick
  4. QML animation blocked when integrating QQuickWidget(QML) and qwidget(VTK) in Python
Forum Updated to NodeBB v4.3 + New Features

QML animation blocked when integrating QQuickWidget(QML) and qwidget(VTK) in Python

Scheduled Pinned Locked Moved Unsolved QML and Qt Quick
1 Posts 1 Posters 308 Views
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • C Offline
    C Offline
    ColinZ
    wrote on 26 Jan 2022, 07:06 last edited by
    #1

    I used QVTKRenderWindowInteractor to integrate VTK in QApplication.
    I also use QQuickWidget to load a QML file, which contains few QtQuick Modules, in to the QApplication.
    The application can run, and I can get the data from the slider in QML when slider moved.

    However, the animation of all modules inside the QML is blocked at first.
    I can get the animation back by click the QQuickWidget first, let it gets focus, and then resize the application window or click the screen area outside the application window.
    The animation will block again once I click the VTK area.

    I had a hard time identifing the problem, can any body help me?

    This is the Python file

    import sys
    
    from PyQt5 import QtWidgets, QtGui
    from vtk.qt.QVTKRenderWindowInteractor import QVTKRenderWindowInteractor
    from vtkmodules.vtkFiltersSources import vtkSphereSource
    from vtkmodules.vtkRenderingCore import (
        vtkActor,
        vtkPolyDataMapper,
        vtkRenderer
    )
    from PyQt5.QtQuickWidgets import QQuickWidget
    from PyQt5.QtCore import QUrl, QObject, pyqtSlot
    
    
    def getVTKWidget(parentFrame):
        # Create source
        source = vtkSphereSource()
        source.SetCenter(0, 0, 0)
        source.SetRadius(5.0)
        # Create a mapper
        mapper = vtkPolyDataMapper()
        mapper.SetInputConnection(source.GetOutputPort())
        # Create an actor
        actor = vtkActor()
        actor.SetMapper(mapper)
        ren = vtkRenderer()
        ren.AddActor(actor)
        ren.ResetCamera()
    
        vtkWidget = QVTKRenderWindowInteractor(parentFrame)
        vtkWidget.GetRenderWindow().AddRenderer(ren)
        vtkWidget.GetRenderWindow().GetInteractor().Initialize()
        vtkWidget.GetRenderWindow().Render()
    
        return vtkWidget, ren
    
    
    class my_QQWidget(QQuickWidget):
    
        def __init__(self):
            super().__init__()
            self.setSource(QUrl.fromLocalFile('./Demo/rect.qml'))
    
        def focusOutEvent(self, event: QtGui.QFocusEvent) -> None:
            super().focusOutEvent(event)
            print('out')
    
    
        def focusInEvent(self, event: QtGui.QFocusEvent) -> None:
            super().focusInEvent(event)
            print('in')
            # print(self.rootObject().findChild(QObject, 'axisComboBox').isFocusScope())
            # print(self.rootObject().findChild(QObject, 'textDegree').isFocusScope())
            # print(self.rootObject().findChild(QObject, 'rectangle').isFocusScope())
            # print(self.rootObject().findChild(QObject, 'angleText').isFocusScope())
            # print(self.rootObject().findChild(QObject, 'resetBtn').isFocusScope())
            # print(self.rootObject().findChild(QObject, 'sliderContainer').isFocusScope())
            # print(self.rootObject().findChild(QObject, 'groove').isFocusScope())
            # print(self.rootObject().findChild(QObject, 'handle').isFocusScope())
            # print(self.rootObject().findChild(QObject, 'slider').isFocusScope())
            self.update()
            self.rootObject().update()
            self.rootObject().updatePolish()
            self.updateGeometry()
            # print(self.focusWidget())
            self.show()
            # print(self.rootObject().hasFocus())
            self.rootObject().polish()
    
    
    def getQQWidget():
        # qqWidget = QQuickWidget()
        # qqWidget.setSource(QUrl.fromLocalFile('./Demo/rect.qml'))
        qqWidget = my_QQWidget()
        return qqWidget
    
    if __name__ == '__main__':
        app = QtWidgets.QApplication(sys.argv)
        # main application window
        window = QtWidgets.QMainWindow()
        # QFrame that holds vtk
        vtkframe = QtWidgets.QFrame()
        vl = QtWidgets.QVBoxLayout()
        vtkframe.setLayout(vl)
        # add vtkWidget
        vtkWidget, ren = getVTKWidget(vtkframe)
        vl.addWidget(vtkWidget)
    
        # QFrame that holds QQuickWidget convert from QML file
        qmlFrame = QtWidgets.QFrame()
        ql = QtWidgets.QVBoxLayout()
        qmlFrame.setLayout(ql)
        # add QQuickWidget (QML file)
        qmlWidget = getQQWidget()
        ql.addWidget(qmlWidget)
    
        # a slider in QQuickWidget
        slider = qmlWidget.rootObject().findChild(QObject, 'slider')
        # slider moved event
        @pyqtSlot()
        def receive_angle():
            angle = slider.property("value")
            print(f"{angle} Degree")
            can = ren.GetActiveCamera()
            can.Azimuth(5)
            vtkWidget.GetRenderWindow().Render()
        slider.moved.connect(receive_angle)
    
        # place vtk frame and qml frame in QVBoxLayout
        mainFrame = QtWidgets.QFrame()
        ml = QtWidgets.QVBoxLayout()
        mainFrame.setLayout(ml)
        ml.addWidget(vtkframe)
        ml.addWidget(qmlFrame)
    
        window.setCentralWidget(mainFrame)
        window.show()
    
        sys.exit(app.exec_())
    
    

    And this is the UI, qml file

    import QtQuick 2.15
    import QtQuick.Controls 2.15
    import QtQuick.Timeline 1.0
    
    Item {
        id: applicationwindow
        objectName: "applicationwindow"
        width: 1024
        height: 150
    
            ComboBox {
                id: comboBox
                objectName: "axisComboBox"
                x: 122
                y: 68
                font.pointSize: 20
                model: ["X Axis", 'Y Axis', 'Z Axis']
                currentIndex: 1
            }
    
            Text {
                id: text1
                objectName: "textDegree"
                x: 827
                y: 67
                width: 79
                height: 40
                text: qsTr("Degree")
                font.pixelSize: 25
                verticalAlignment: Text.AlignVCenter
            }
    
            Rectangle {
                id: rectangle
                objectName: "rectangle"
                x: 760
                y: 67
                width: 55
                height: 40
                color: "lightgrey"
                border.color: "grey"
    
                TextInput {
                    id: textEdit
                    objectName: "angleText"
                    validator: IntValidator {
                        bottom: 0
                        top: 360
                    }
                    maximumLength: 3
                    text: qsTr("0")
                    anchors.fill: parent
                    font.pixelSize: 26
                    horizontalAlignment: Text.AlignRight
                    verticalAlignment: Text.AlignVCenter
                }
            }
    
            Button {
                id: button
                objectName: "resetBtn"
                x: 462
                y: 19
                text: qsTr("Reset")
                font.pixelSize: 26
            }
    
    
        Item {
            id: sliderContainer
             objectName: "sliderContainer"
            x: 275
            y: 73
            width: 474
            height: 31
            Image {
                id: sliderContainerAsset
                source: "assets/sliderContainer.png"
            }
    
            Image {
                id: groove
                objectName: "groove"
                y: 0
                anchors.left: parent.left
                anchors.right: parent.right
                source: "assets/groove.png"
                anchors.leftMargin: 0
                anchors.rightMargin: 0
            }
    
            Image {
                id: handle
                objectName: "handle"
                x: 444
                y: 1
                anchors.verticalCenter: parent.verticalCenter
                anchors.bottom: parent.bottom
                source: "assets/handle.png"
                anchors.verticalCenterOffset: 0
                anchors.bottomMargin: 0
            }
    
            Slider {
                id: slider
                objectName: "slider"
                anchors.fill: parent
                value: 0
                stepSize: 1
                to: 180
            }
        }
    
        Timeline {
            id: timeline
            currentFrame: slider.value
            KeyframeGroup {
                target: handle
                property: "x"
                Keyframe {
                    value: 444
                    frame: 180
                }
    
                Keyframe {
                    value: 0
                    frame: 0
                }
            }
            endFrame: 180
            enabled: true
            startFrame: 0
        }
    }
    
    /*##^##
    Designer {
        D{i:0;formeditorZoom:0.5}D{i:1}D{i:2}D{i:4}D{i:3}D{i:6}D{i:8}D{i:9}D{i:10}D{i:11}
    D{i:7}D{i:12}
    }
    ##^##*/
    
    

    55e8610e-76f5-4564-83d4-366a99f315dd-image.png

    1 Reply Last reply
    0

    1/1

    26 Jan 2022, 07:06

    • Login

    • Login or register to search.
    1 out of 1
    • First post
      1/1
      Last post
    0
    • Categories
    • Recent
    • Tags
    • Popular
    • Users
    • Groups
    • Search
    • Get Qt Extensions
    • Unsolved