1

Right now, I am learning QGraphicsView. I followed a tutorial given by Nokia from 2011 (YouTube: Qt DevDays 2011, Advanced Qt -A Deep Dive 1/6). It is a very basic demo showing a house (made from QRect and QPolygon) that turns around if clicked. On the backside of the house are a few widgets (e.g. QCombobox) aranged inside a QGraphicsProxyWidget hold by a QGraphicsItemGroup. Now I am facing the problem that since Qt 4.7 the class QGraphicItemsGroup no longer supports the flag "setHandlesChildEvents(False)".

Since QGraphicsItemGroup will handle all the events, how can I achieve that the QGraphicsItem Group will not block the child item's event, as well as letting child item handle it own event?

Thanks in advance for your help!

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
David C.
  • 1,974
  • 2
  • 19
  • 29
SVerpoort
  • 11
  • 2
  • I found a solution self.setHandlesChildEvents(False) (works for 5.14 but should work for yours, too) here https://stackoverflow.com/questions/3021441/events-with-qgraphicsitemgroup. – moin moin Jan 15 '20 at 13:10

0 Answers0