Dàvid Nagy
Dàvid Nagy

Reputation: 159

Changing the color of a QGraphicsItem

I am working on a simple software, which has a GUI. (I'm using PyQt) I have 2 radiobuttons. If the first is selected, then by clicking on the Graphicsscene a GraphicsItem will be added to the scene. I would like to have a button, which would change the color of these points by pressing it. The color doesn't matter. It could be red for example. How could I do that? Thank you!

For placing the widgets I used the Qt Designer, and then created a subclass called SimpleWindow.

Here is the code: The points class:

from PyQt5.QtCore import QRectF, Qt
from PyQt5.QtWidgets import QGraphicsItem

class Point(QGraphicsItem):
    def __init__(self, x, y):
        super(Point, self).__init__()
        self.setFlag(QGraphicsItem.ItemIsSelectable, True)
        self.rectF = QRectF(0, 0, 4, 4)
        self.x=x
        self.y=y

    def boundingRect(self):
        return self.rectF

    def paint(self, painter=None, style=None, widget=None):
        painter.fillRect(self.rectF, Qt.black)

import sys
from PyQt5 import QtCore, QtWidgets
from PyQt5.QtGui import QPen, QBrush
from PyQt5.QtWidgets import QGraphicsScene

The scene:

class PointsGraphicsScene(QGraphicsScene):
    def __init__(self, parent=None):
        QGraphicsScene.__init__(self, parent)
        self.setSceneRect(0, 0, 200, 200)
        self.opt = ""

    def setOption(self, opt):
        self.opt = opt

    def mousePressEvent(self, event):
        pen = QPen(QtCore.Qt.black)
        brush = QBrush(QtCore.Qt.black)
        x = event.scenePos().x()
        y = event.scenePos().y()
        if self.opt == "Generate":
            p = point.Point(x, y)
            p.setPos(x, y)
            self.addItem(p)
        elif self.opt == "Select":
            print(x, y)

The dialog window:

import sys
from PyQt5 import QtCore, QtWidgets
from PyQt5.QtWidgets import QButtonGroup
import window
from scene import PointsGraphicsScene

class SimpleWindow(QtWidgets.QMainWindow, window.Ui_Dialog):
    def __init__(self, parent=None):
        super(SimpleWindow, self).__init__(parent)
        self.setupUi(self)
        self.scene = PointsGraphicsScene(self)
        self.graphicsView.setScene(self.scene)
        self.graphicsView.setAlignment(QtCore.Qt.AlignLeft | 
        QtCore.Qt.AlignTop)

        group = QButtonGroup(self)
        group.addButton(self.radioButton)
        group.addButton(self.radioButton_2)

        group.buttonClicked.connect(lambda btn: 
        self.scene.setOption(btn.text()))
        self.radioButton.setChecked(True)
        self.scene.setOption(self.radioButton.text())


app = QtWidgets.QApplication(sys.argv)
form = SimpleWindow()
form.show()
app.exec_()

This is the the class generated by the Designer.

from PyQt5 import QtCore, QtGui, QtWidgets

class Ui_Dialog(object):
    def setupUi(self, Dialog):
        Dialog.setObjectName("Dialog")
        Dialog.resize(538, 269)
        self.graphicsView = QtWidgets.QGraphicsView(Dialog)
        self.graphicsView.setGeometry(QtCore.QRect(130, 10, 371, 221))
        self.graphicsView.setObjectName("graphicsView")
        self.radioButton = QtWidgets.QRadioButton(Dialog)
        self.radioButton.setGeometry(QtCore.QRect(20, 30, 82, 31))
        self.radioButton.setObjectName("radioButton")
        self.radioButton_2 = QtWidgets.QRadioButton(Dialog)
        self.radioButton_2.setGeometry(QtCore.QRect(20, 80, 82, 17))
        self.radioButton_2.setObjectName("radioButton_2")

        self.retranslateUi(Dialog)
        QtCore.QMetaObject.connectSlotsByName(Dialog)

    def retranslateUi(self, Dialog):
        _translate = QtCore.QCoreApplication.translate
        Dialog.setWindowTitle(_translate("Dialog", "Dialog"))
        self.radioButton.setText(_translate("Dialog", "Generate"))
        self.radioButton_2.setText(_translate("Dialog", "Select"))

Upvotes: 5

Views: 8402

Answers (1)

eyllanesc
eyllanesc

Reputation: 244301

The first thing is to create a method that changes the color, in this case we will call it setBrush():

class Point(QGraphicsItem):
    def __init__(self, x, y):
        super(Point, self).__init__()
        self.setFlag(QGraphicsItem.ItemIsSelectable, True)
        self.rectF = QRectF(0, 0, 4, 4)
        self.x=x
        self.y=y
        self._brush = QBrush(Qt.black)

    def setBrush(self, brush):
        self._brush = brush
        self.update()

    def boundingRect(self):
        return self.rectF

    def paint(self, painter=None, style=None, widget=None):
        painter.fillRect(self.rectF, self._brush)

The second thing to do is create the button and locate it in some position. then the QPushButton clicked signal is connected to some slot. Then we get the items of the scene through the items() method and change the color with setBrush():

class SimpleWindow(QtWidgets.QMainWindow, window.Ui_Dialog):
    def __init__(self, parent=None):
        super(SimpleWindow, self).__init__(parent)
        self.setupUi(self)
        self.scene = PointsGraphicsScene(self)
        self.graphicsView.setScene(self.scene)
        self.graphicsView.setAlignment(QtCore.Qt.AlignLeft |
        QtCore.Qt.AlignTop)

        group = QButtonGroup(self)
        group.addButton(self.radioButton)
        group.addButton(self.radioButton_2)

        group.buttonClicked.connect(lambda btn:
        self.scene.setOption(btn.text()))
        self.radioButton.setChecked(True)
        self.scene.setOption(self.radioButton.text())

        button = QPushButton("change color", self)
        button.move(20, 140)

        button.clicked.connect(self.onClicked)

    def onClicked(self):
        for item in self.scene.items():
            item.setBrush(QColor("red"))


app = QtWidgets.QApplication(sys.argv)
form = SimpleWindow()
form.show()
app.exec_()

Upvotes: 2

Related Questions