让QGraphicsItemGroup的孩子处理他们自己的事件

时间:2017-03-04 20:12:16

标签: python qt

现在,我正在学习QGraphicsView。我按照诺基亚从2011年开始的教程(YouTube:Qt DevDays 2011,Advanced Qt -A Deep Dive 1/6)。这是一个非常基本的演示,显示了一个房子(由QRect和QPolygon制成),如果点击它就会转过来。在房子的背面有一些小部件(例如QCombobox),它们由QGraphicsItemGroup保存在QGraphicsProxyWidget中。现在我面临的问题是,自Qt 4.7以来,类QGraphicItemsGroup不再支持标志“setHandlesChildEvents(False)”。

由于QGraphicsItemGroup将处理所有事件,我如何实现QGraphicsItem组不会阻止子项的事件,以及让子项处理它自己的事件?

提前感谢您的帮助!

  

main_house.py

from PyQt5.QtWidgets import QApplication, QGraphicsScene, QGraphicsView
from PyQt5.QtCore import Qt
import sys
from House.house import House

app = QApplication([])
scene = QGraphicsScene()

house_1 = House(Qt.blue, Qt.yellow)
scene.addItem(house_1)

scene.setSceneRect(0, 0, 500, 500)
view = QGraphicsView(scene)
view.show()
view.resize(600, 600)
sys.exit(app.exec_())
  

house.py

from PyQt5.QtWidgets import QGraphicsItemGroup,QGraphicsProxyWidget,QGraphicsRectItem,QGraphicsPolygonItem, \
QWidget, QVBoxLayout, QLabel, QComboBox, QPushButton
from PyQt5.QtCore import QTimeLine, QPointF, QRectF, Qt
from PyQt5.QtGui import QColor, QPolygonF, QTransform


class House(QGraphicsItemGroup):
    def __init__(self, roofcolor: QColor, facadecolor: QColor, parent=None):
        super(House, self).__init__(parent)


        self._front = True
        self._timeline = None
        self._graphics = None
        self._configpage = None
        self._facade = None
        self._roof = None

        self.roof_polygon = QPolygonF()
        self.roof_polygon << QPointF(0, 200) << QPointF(100, 0) << QPointF(200, 200)

        self.body_rect = QRectF(0, 200, 200, 200)

        self.create_roof(roofcolor)
        self.create_front(facadecolor)
        self.create_back(roofcolor, facadecolor)

        # ==========================
        # self.setHandlesChildEvents(False)  # obsolete since Qt 4.7
        # ==========================

    def mousePressEvent(self, event):
        if not self._timeline:
            self._timeline = QTimeLine(1000)
            self._timeline.setCurveShape(QTimeLine.EaseInOutCurve)
            self._timeline.valueChanged.connect(self.rotate_house)
            self._timeline.finished.connect(self.reset)
            self._timeline.start()

    def reset(self):
        self._timeline = None

    def rotate_house(self, pos):
        angle = int(pos * 180)
        if self._front is True:
            angle += 180
        transform = QTransform()
        transform.translate(100, 0)
        transform.rotate(angle, Qt.YAxis)
        transform.translate(-100, 0)
        self.setTransform(transform)

        if pos == 1.0:
            self._front = not self._front

        config = angle < 90 or angle >= 270
        self._configpage.setVisible(config)
        self._facade.setVisible(not config)

    def update_roof_color(self):
        combo = self.sender()
        color = combo.itemData(combo.currentIndex()).value()
        self._roof.setBrush(color)

    def update_house_color(self):
        combo = self.sender()
        color = combo.itemData(combo.currentIndex()).value()
        self._facade.setBrush(color)

    def create_roof(self, color: QColor):
        self._roof = QGraphicsPolygonItem(self.roof_polygon)
        self.addToGroup(self._roof)
        self._roof.setBrush(color)

    def create_front(self, color: QColor):
        self._facade = QGraphicsRectItem(self.body_rect)
        self._facade.setBrush(color)
        self.addToGroup(self._facade)

    def create_back(self, roof_color: QColor, facade_color: QColor):
        self._configpage = QGraphicsProxyWidget()
        self._configpage.setWidget(self.create_config_widget(roof_color, facade_color))
        self._configpage.setGeometry(self.body_rect)
        self.addToGroup(self._configpage)
        self._configpage.hide()

    # ==== Problem: Widgets (comboboxes) do not receive events ====
    def create_config_widget(self, roof_color: QColor, facade_color: QColor) -> QWidget:
        res = QWidget()
        layout = QVBoxLayout(res)
        label = QLabel('Roof color:')
        layout.addWidget(label)
        self.roof_combo = self.create_color_combobox(roof_color)  # combobox does not receive events
        layout.addWidget(self.roof_combo)
        self.roof_combo.activated.connect(self.update_roof_color)
        label = QLabel('House color:')
        layout.addWidget(label)
        self.facade_combo = self.create_color_combobox(facade_color)
        layout.addWidget(self.facade_combo)
        self.facade_combo.activated.connect(self.update_house_color)
        bt = QPushButton('Test')
        bt.setCheckable(True)
        layout.addWidget(bt)
        layout.addStretch(1)
        return res

    def create_color_combobox(self, color: QColor) -> QComboBox:
        res = QComboBox()
        res.addItem('red', QColor(Qt.red))
        res.addItem('blue', QColor(Qt.blue))
        res.addItem('green', QColor(Qt.green))
        res.addItem('white', QColor(Qt.white))
        res.setCurrentIndex(res.findData(color))
        return res

0 个答案:

没有答案