Что не так с механизмом обратного вызова в PyQt5.Qt3DCore с использованием примера QT - PullRequest
0 голосов
/ 17 мая 2018

Я заново реализовал пример кода Qt3D в PyQt5 / Python3 с этого сайта: https://doc.qt.io/qt-5/qt3d-basicshapes-cpp-main-cpp.html

Хотя объекты отображаются правильно, обратные вызовы не работают. Когда я нажимаю на флажки, обратные вызовы не активируются. Я пробовал разные вещи (pyqtSlots, pyqtSignal decoratos и т. Д., Но не могу понять.

Что я делаю не так? Любые предложения будут с благодарностью.

    #
#
#  Copyright (C) 2014 Klaralvdalens Datakonsult AB (KDAB).
#  Contact: https:#www.qt.io/licensing/
#
#  This file is part of the Qt3D module of the Qt Toolkit.
#
#  $QT_BEGIN_LICENSE:BSD$
#  Commercial License Usage
#  Licensees holding valid commercial Qt licenses may use this file in
#  accordance with the commercial license agreement provided with the
#  Software or, alternatively, in accordance with the terms contained in
#  a written agreement between you and The Qt Company. For licensing terms
#  and conditions see https:#www.qt.io/terms-conditions. For further
#  information use the contact form at https:#www.qt.io/contact-us.
#
#  BSD License Usage
#  Alternatively, you may use this file under the terms of the BSD license
#  as follows:
#
#  "Redistribution and use in source and binary forms, with or without
#  modification, are permitted provided that the following conditions are
#  met:
#    * Redistributions of source code must retain the above copyright
#      notice, this list of conditions and the following disclaimer.
#    * Redistributions in binary form must reproduce the above copyright
#      notice, this list of conditions and the following disclaimer in
#      the documentation and/or other materials provided with the
#      distribution.
#    * Neither the name of The Qt Company Ltd nor the names of its
#      contributors may be used to endorse or promote products derived
#      from this software without specific prior written permission.
#
#
#  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
#  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
#  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
#  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
#  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
#  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
#  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES
#  LOSS OF USE,
#  DATA, OR PROFITS
#  OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
#  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
#  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
#  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
#
#  $QT_END_LICENSE$
#
#

# See
# https://doc.qt.io/qt-5/qt3d-basicshapes-cpp-scenemodifier-cpp.html
#   and
# https://doc.qt.io/qt-5/qt3d-basicshapes-cpp-main-cpp.html

# Use this requirements.txt
###########################################
# PyQt3D==5.10.1
# PyQt5==5.10.1
# pyqt5-tools==5.9.0.1.2
# QScintilla==2.10.4
# sip==4.19.8

# Python version:
#  Python 3.6.5 (v3.6.5:f59c0932b4, Mar 28 2018, 16:07:46) [MSC v.1900 32 bit (Intel)] on win32

from PyQt5.QtWidgets import QApplication, QWidget, QHBoxLayout, QCheckBox, QCommandLinkButton, \
    QVBoxLayout
from PyQt5.Qt import Qt as _Qt
from PyQt5.QtGui import QColor, QVector3D, QQuaternion
from PyQt5.Qt3DInput import QInputAspect
from PyQt5.Qt3DExtras import QTorusMesh, QPhongMaterial, QConeMesh, QCylinderMesh, \
    QCuboidMesh, QPlaneMesh, QSphereMesh, Qt3DWindow, QFirstPersonCameraController
from PyQt5.Qt3DRender import QPointLight
from PyQt5.Qt3DCore import QEntity, QTransform
from PyQt5.QtCore import QSize, pyqtSlot, pyqtSignal

import sys


class SceneModifier(QEntity):
    def __init__(self, rootEntity):
        self.m_rootEntity = rootEntity
        # Torus shape data
        self.m_torus = QTorusMesh()
        self.m_torus.setRadius(1.0)
        self.m_torus.setMinorRadius(0.4)
        self.m_torus.setRings(100)
        self.m_torus.setSlices(20)

        # TorusMesh Transform
        self.torusTransform = QTransform()
        self.torusTransform.setScale(2.0)
        self.torusTransform.setRotation(QQuaternion.fromAxisAndAngle(QVector3D(0.0, 1.0, 0.0), 25.0))
        self.torusTransform.setTranslation(QVector3D(5.0, 4.0, 0.0))

        self.torusMaterial = QPhongMaterial()
        self.torusMaterial.setDiffuse(QColor(0xbeb32b))

        # Torus
        self.m_torusEntity = QEntity(self.m_rootEntity)
        self.m_torusEntity.addComponent(self.m_torus)
        self.m_torusEntity.addComponent(self.torusMaterial)
        self.m_torusEntity.addComponent(self.torusTransform)

        # self.cone shape data
        self.cone = QConeMesh()
        self.cone.setTopRadius(0.5)
        self.cone.setBottomRadius(1)
        self.cone.setLength(3)
        self.cone.setRings(50)
        self.cone.setSlices(20)

        # ConeMesh Transform
        self.coneTransform = QTransform()
        self.coneTransform.setScale(1.5)
        self.coneTransform.setRotation(QQuaternion.fromAxisAndAngle(QVector3D(1.0, 0.0, 0.0), 45.0))
        self.coneTransform.setTranslation(QVector3D(0.0, 4.0, -1.5))

        self.coneMaterial = QPhongMaterial()
        self.coneMaterial.setDiffuse(QColor(0x928327))

        # Cone
        self.m_coneEntity = QEntity(self.m_rootEntity)
        self.m_coneEntity.addComponent(self.cone)
        self.m_coneEntity.addComponent(self.coneMaterial)
        self.m_coneEntity.addComponent(self.coneTransform)

        # Cylinder shape data
        self.cylinder = QCylinderMesh()
        self.cylinder.setRadius(1)
        self.cylinder.setLength(3)
        self.cylinder.setRings(100)
        self.cylinder.setSlices(20)

        # CylinderMesh Transform
        self.cylinderTransform = QTransform()
        self.cylinderTransform.setScale(1.5)
        self.cylinderTransform.setRotation(QQuaternion.fromAxisAndAngle(QVector3D(1.0, 0.0, 0.0), 45.0))
        self.cylinderTransform.setTranslation(QVector3D(-5.0, 4.0, -1.5))

        self.cylinderMaterial = QPhongMaterial()
        self.cylinderMaterial.setDiffuse(QColor(0x928327))

        # Cylinder
        self.m_cylinderEntity = QEntity(self.m_rootEntity)
        self.m_cylinderEntity.addComponent(self.cylinder)
        self.m_cylinderEntity.addComponent(self.cylinderMaterial)
        self.m_cylinderEntity.addComponent(self.cylinderTransform)

        # Cuboid shape data
        self.cuboid = QCuboidMesh()

        # CuboidMesh Transform
        self.cuboidTransform = QTransform()
        self.cuboidTransform.setScale(4.0)
        self.cuboidTransform.setTranslation(QVector3D(5.0, -4.0, 0.0))

        self.cuboidMaterial = QPhongMaterial()
        self.cuboidMaterial.setDiffuse(QColor(0x665423))

        #Cuboid
        self.m_cuboidEntity = QEntity(self.m_rootEntity)
        self.m_cuboidEntity.addComponent(self.cuboid)
        self.m_cuboidEntity.addComponent(self.cuboidMaterial)
        self.m_cuboidEntity.addComponent(self.cuboidTransform)

        # Plane shape data
        self.planeMesh = QPlaneMesh()
        self.planeMesh.setWidth(2)
        self.planeMesh.setHeight(2)

        # Plane mesh transform
        self.planeTransform = QTransform()
        self.planeTransform.setScale(1.3)
        self.planeTransform.setRotation(QQuaternion.fromAxisAndAngle(QVector3D(1.0, 0.0, 0.0), 45.0))
        self.planeTransform.setTranslation(QVector3D(0.0, -4.0, 0.0))

        self.planeMaterial = QPhongMaterial()
        self.planeMaterial.setDiffuse(QColor(0xa69929))

        # Plane
        self.m_planeEntity = QEntity(self.m_rootEntity)
        self.m_planeEntity.addComponent(self.planeMesh)
        self.m_planeEntity.addComponent(self.planeMaterial)
        self.m_planeEntity.addComponent(self.planeTransform)

        # Sphere shape data
        self.sphereMesh = QSphereMesh()
        self.sphereMesh.setRings(20)
        self.sphereMesh.setSlices(20)
        self.sphereMesh.setRadius(2)

        # Sphere mesh transform
        self.sphereTransform = QTransform()

        self.sphereTransform.setScale(1.3)
        self.sphereTransform.setTranslation(QVector3D(-5.0, -4.0, 0.0))

        self.sphereMaterial = QPhongMaterial()
        self.sphereMaterial.setDiffuse(QColor(0xa69929))

        # Sphere
        self.m_sphereEntity = QEntity(self.m_rootEntity)
        self.m_sphereEntity.addComponent(self.sphereMesh)
        self.m_sphereEntity.addComponent(self.sphereMaterial)
        self.m_sphereEntity.addComponent(self.sphereTransform)

    def enableTorus(self, enabled):
        print("set enabled")
        self.m_torusEntity.setEnabled(enabled)

    def enableCone(self, enabled):
        self.m_coneEntity.setEnabled(enabled)

    def enableCylinder(self, enabled):
        self.m_cylinderEntity.setEnabled(enabled)

    def enableCuboid(self, enabled):
        self.m_cuboidEntity.setEnabled(enabled)

    def enablePlane(self, enabled):
        self.m_planeEntity.setEnabled(enabled)

    def enableSphere(self, enabled):
        self.m_sphereEntity.setEnabled(enabled)


if __name__ == "__main__":

    app = QApplication(sys.argv)
    view = Qt3DWindow()
    view.defaultFrameGraph().setClearColor(QColor(0x4d4d4f))
    container = QWidget.createWindowContainer(view)
    screenSize = view.screen().size()
    container.setMinimumSize(200, 100)
    container.setMaximumSize(screenSize)

    widget = QWidget()
    hLayout = QHBoxLayout(widget)
    vLayout = QVBoxLayout()
    vLayout.setAlignment(_Qt.AlignTop)
    hLayout.addWidget(container, 1)
    hLayout.addLayout(vLayout)

    widget.setWindowTitle("Basic shapes")

    input = QInputAspect()
    view.registerAspect(input)

    # Root entity
    rootEntity = QEntity()

    # Camera
    cameraEntity = view.camera()

    cameraEntity.lens().setPerspectiveProjection(45.0, 16.0/9.0, 0.1, 1000.0)
    cameraEntity.setPosition(QVector3D(0, 0, 20.0))
    cameraEntity.setUpVector(QVector3D(0, 1, 0))
    cameraEntity.setViewCenter(QVector3D(0, 0, 0))

    lightEntity = QEntity(rootEntity)
    light = QPointLight(lightEntity)
    light.setColor(_Qt.white)
    light.setIntensity(1)
    lightEntity.addComponent(light)
    lightTransform = QTransform(lightEntity)
    lightTransform.setTranslation(cameraEntity.position())
    lightEntity.addComponent(lightTransform)

    # For camera controls
    camController = QFirstPersonCameraController(rootEntity)
    camController.setCamera(cameraEntity)

    # Scenemodifier
    modifier = SceneModifier(rootEntity)

    # Set root object of the scene
    view.setRootEntity(rootEntity)

    # Create control widgets
    info = QCommandLinkButton()
    info.setText("Qt3D ready-made meshes")
    info.setDescription("Qt3D provides several ready-made meshes, like torus, cylinder, cone, "
                                             "cube, plane and sphere.")
    info.setIconSize(QSize(0,0))
    torusCB = QCheckBox(widget)
    torusCB.setChecked(True)
    torusCB.setText("Torus")

    coneCB = QCheckBox(widget)
    coneCB.setChecked(True)
    coneCB.setText("Cone")

    cylinderCB = QCheckBox(widget)
    cylinderCB.setChecked(True)
    cylinderCB.setText("Cylinder")

    cuboidCB = QCheckBox(widget)
    cuboidCB.setChecked(True)
    cuboidCB.setText("Cuboid")

    planeCB = QCheckBox(widget)
    planeCB.setChecked(True)
    planeCB.setText("Plane")

    sphereCB = QCheckBox(widget)
    sphereCB.setChecked(True)
    sphereCB.setText("Sphere")

    vLayout.addWidget(info)
    vLayout.addWidget(torusCB)
    vLayout.addWidget(coneCB)
    vLayout.addWidget(cylinderCB)
    vLayout.addWidget(cuboidCB)
    vLayout.addWidget(planeCB)
    vLayout.addWidget(sphereCB)

    torusCB.stateChanged.connect(modifier.enableTorus)
    coneCB.stateChanged.connect(modifier.enableCone)
    cylinderCB.stateChanged.connect(modifier.enableCylinder)
    cuboidCB.stateChanged.connect(modifier.enableCuboid)
    planeCB.stateChanged.connect(modifier.enablePlane)
    sphereCB.stateChanged.connect(modifier.enableSphere)

    torusCB.setChecked(True)
    coneCB.setChecked(True)
    cylinderCB.setChecked(True)
    cuboidCB.setChecked(True)
    planeCB.setChecked(True)
    sphereCB.setChecked(True)
    widget.show()
    widget.resize(1200, 800)

    sys.exit(app.exec())

Это изображение:

enter image description here

1 Ответ

0 голосов
/ 17 мая 2018

Кажется, что это ошибка PyQt3D, возможное решение - использовать functools.partial:

...

from functools import partial

torusCB.stateChanged.connect(partial(modifier.enableTorus))
coneCB.stateChanged.connect(partial(modifier.enableCone))
cylinderCB.stateChanged.connect(partial(modifier.enableCylinder))
cuboidCB.stateChanged.connect(partial(modifier.enableCuboid))
planeCB.stateChanged.connect(partial(modifier.enablePlane))
sphereCB.stateChanged.connect(partial(modifier.enableSphere))

...
...