SetEnabled QEntity не работает должным образом, когда сущности создаются в методе, вызванном сигналом - PullRequest
0 голосов
/ 20 сентября 2018

QEntity, созданный в методе, вызываемом сигналом, не работает должным образом.

Вызов метода setEnabled(True) или setEnabled(False) при QEntity не оказывает влияния.

Ниже приведен рабочий пример:

import numpy as np

from PySide2.QtCore import Qt, QObject, Slot, Signal, QThread
from PySide2.QtGui import QVector3D
from PySide2.Qt3DCore import Qt3DCore
from PySide2.QtWidgets import (
    QApplication, QWidget, QVBoxLayout, QHBoxLayout, QCheckBox, QPushButton,
)
from PySide2.Qt3DExtras import Qt3DExtras


class Worker(QObject):
    @Slot()
    def do_work(self):
        self.sig_done.emit(None)
        self.sig_stopped.emit()

    sig_done = Signal(object)
    sig_stopped = Signal()


class Sphere(Qt3DCore.QEntity):
    def __init__(self, parent):
        super().__init__(parent)
        self.data = []
        self.mesh = Qt3DExtras.QSphereMesh()
        self.mesh.setRadius(.5)
        self.transform = Qt3DCore.QTransform()
        location = np.random.rand(3) * 10
        self.transform.setTranslation(QVector3D(*location))
        self.material = Qt3DExtras.QPhongMaterial(self)

        self.addComponent(self.material)
        self.addComponent(self.mesh)
        self.addComponent(self.transform)

    def toggle(self):
        if self.isEnabled():
            self.setEnabled(False)
        else:
            self.setEnabled(True)

    def setEnabled(self, is_enabled):
        print("Hello from Sphere!", is_enabled)
        super().setEnabled(is_enabled)


class Spheres(Qt3DCore.QEntity):
    def __init__(self, parent):
        super().__init__(parent)
        self.container = [Sphere(self) for _ in range(10)]

    def setEnabled(self, is_enabled):
        print("Hello from Sphere Container!", is_enabled)
        super().setEnabled(is_enabled)


class Window(Qt3DExtras.Qt3DWindow):
    def __init__(self):
        super().__init__()
        self.resize(300, 300)
        # Root entity
        self.root_entity = Qt3DCore.QEntity()
        # Camera
        self.cameraEntity = self.camera()
        self.camera().lens().setPerspectiveProjection(45.0, 16.0 / 9.0, 0.1, 1000.0)
        self.camera().setPosition(QVector3D(20.0, 20.0, 20.0))
        self.camera().setUpVector(QVector3D(0, 1, 0))
        self.camera().setViewCenter(QVector3D(0, 0, 0))
        # For camera controls
        self.camera_controller = Qt3DExtras.QFirstPersonCameraController(self.root_entity)
        self.camera_controller.setCamera(self.camera())

        self.spheres = None
        self.setRootEntity(self.root_entity)

    def load(self):
        self.spheres = Spheres(self.root_entity)


class Widget(QWidget):
    def __init__(self):
        super().__init__()
        self.view = Window()
        self.container = self.createWindowContainer(self.view)

        hLayout = QHBoxLayout(self)
        self.vLayout = QVBoxLayout()
        self.vLayout.setAlignment(Qt.AlignTop)
        hLayout.addWidget(self.container, 1)
        hLayout.addLayout(self.vLayout)

        self.cb_spheres = None
        self.cb_single_sphere = None

        # ***** These lines cause problems:
        self._thread = QThread()
        self._worker = Worker()
        self._worker.moveToThread(self._thread)
        self._worker.sig_stopped.connect(self._thread.quit)
        self._worker.sig_done.connect(self.load)
        self._thread.started.connect(self._worker.do_work)
        self._thread.start()
        # *****

    @Slot()
    def load(self):
        self.view.load()
        self.cb_spheres = QCheckBox(self)
        self.cb_spheres.setChecked(True)
        self.cb_spheres.setText("All spheres")
        self.vLayout.addWidget(self.cb_spheres)

        spheres = self.view.spheres

        def func():
            spheres.setEnabled(not spheres.isEnabled())
        self.cb_spheres.stateChanged.connect(func)
        self.cb_single_sphere = []
        for i in range(10):
            self.cb_single_sphere.append(QCheckBox(self))
            self.cb_single_sphere[-1].setChecked(True)
            self.cb_single_sphere[-1].setText("Sphere {}".format(i))
            self.vLayout.addWidget(self.cb_single_sphere[-1])
            self.cb_single_sphere[-1].stateChanged.connect(spheres.container[i].toggle)


if __name__ == '__main__':
    import sys

    app = QApplication(sys.argv)

    w = Widget()
    w.show()
    w.resize(1200, 800)

    sys.exit(app.exec_())

Он работает, когда я заменяю строки между ***** на self.load().

И не работает, когда эти строки заменяются:

self.btn = QPushButton("Load", self)
self.btn.clicked.connect(self.load)
self.vLayout.addWidget(self.btn)

Редактировать: ни одна из них не работает при замене этих строк на:

self.timer = QTimer()
self.timer.setSingleShot(True)
self.timer.setInterval(1000)
self.timer.timeout.connect(self.load)
self.timer.start()

Есть ли способ исправить это?

...