MousePressEvents für Elemente innerhalb QGraphicsItemGroup
Verfasst: Samstag 4. März 2017, 20:31
Ich arbeite mich gerade in das Thema QGraphicsView ein. Dabei habe ich versucht ein C++ Tutorial von Nokia aus dem Jahr 2011 (YouTube: Qt DevDays 2011, Advanced Qt -A Deep Dive 1/6) in Python umzusetzen. Es wird ein einfaches Haus gezeichnet, welches sich beim Mausklick umdreht, auf der Rückseite des Hauses erscheint ein Combobox-Menü für eine Farbauswahl. Hierbei bin ich auf das Problem gestossen, das man bis Qt 4.7 für abgeleitete Klassen der Klasse QGraphicsItemGroup die Eigenschaft setHandlesChildEvents(False) setzten konnte, damit die Events (MousePressEvent usw.) an die Kinder der Gruppe weitergeleitet werden. Diese Funktion ist ab Qt 4.7 obsolet und nicht mehr einsetzbar. Alternativen konnte ich in der Dokumentation nicht finden. Wie kann erreichen, dass die Elemente innerhalb des QGraphicsProxyWidget-Containers die Events erhalten ?
Vielen Dank im voraus !
Datei: main_house.py
Datei: house.py
Vielen Dank im voraus !
Datei: main_house.py
Code: Alles auswählen
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_())
Code: Alles auswählen
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()
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