Home > PyQt5, python > PyQt5: QBrush

PyQt5: QBrush

19 Giugno 2019

Torna all’indice degli appunti

QBrush

La classe QBrush definisce il pattern di riempimento delle figure disegnate con un oggetto QPainter.
I 4 parametri che caratterizzano un oggetto QBrush sono lo stile, il colore, il gradiente e la texture.
Il costruttore QBrush quindi, prende come argomenti lo stile, il colore, il gradiente e la texture:
E’ possibile però costruire l’oggetto senza parametri e poi settarli in un secondo momento.
Un oggetto QBrush ha quindi 4 metodi fondamentali che lo identificano:

style(): indica il pattern di riempimento della figura disegnata;
color(): indica il colore del pattern di riempimento;
gradient(): indica il tipo di gradiente del pattern di riempimento;
texture(): indica il pixmap utilizzato come riempimento;

I corrispondenti setter, che modificano le caratteristiche dell’oggetto QBrush, sono ovviamente setStyle(Qt.BrushStyle), setColor(QColor), setTexture(pixmap). Non è disponibile un setter per il gradiente, ma bisogna passare l’enum corrispondente in fase di costruzione dell’oggetto.

Useremo questo codice per vedere le varie differenze nell’oggetto QBrush:

from PyQt5.QtWidgets import QWidget, QApplication
from PyQt5.QtWidgets import QMainWindow
from PyQt5.QtGui import QPainter, QBrush, QColor
from PyQt5.QtCore import Qt
import sys


class MainWindow(QMainWindow):
    def __init__(self, parent=None):
        super(MainWindow, self).__init__(parent)
        self.setWindowTitle("QBrush Example")
        self.central_widget = FormWidget(self)
        self.setCentralWidget(self.central_widget)
        self.resize(200, 100)


class FormWidget(QWidget):
    def __init__(self, parent):
        super(FormWidget, self).__init__(parent)
        self.painter = None

    def paintEvent(self, event):
        self.painter = QPainter()
        self.painter.begin(self)
        brush = QBrush()
        self.painter.setBrush(brush)
        self.parent().pos()
        self.painter.drawRect(10, 10, 180, 80)
        self.painter.end()


if __name__ == '__main__':
    app = QApplication(sys.argv)
    main_window = MainWindow()
    main_window.show()
    sys.exit(app.exec_())

BRUSH STYLE

Per sapere lo stile di QBrush, come già detto, si usa il metodo style(), invece setStyle(style) setta il tipo di pattern utilizzato;
style è un enum di tipo Qt.BrushStyle e può assumere i seguenti valori:

Costante valore descrizione
Qt.NoBrush 0 Nessuna pattern
Qt.SolidPattern 1 Pattern con colore uniforme
Qt.Dense1Pattern -> Qt.Dense7Pattern 2-8 Pattern con densità crescente da 1 a 7
Qt.HorPattern 9 Pattern con linee orizzontali
Qt.VerPattern 10 Pattern con linee verticali
Qt.CrossPattern 11 Pattern con linee orizzontali e verticali
Qt.BDiagPattern 12 Pattern con linee diagonali
Qt.FDiagPattern 13 Pattern con linee diagonali opposte
Qt.DiagCrossPattern 14 Pattern con linee diagonali incrociate
Qt.LinearGradientPattern 15 Pattern con gradient Lineare
Qt.RadialGradientPattern 16 Pattern con gradient Radial
Qt.ConicalGradientPattern 17 Pattern con gradient Conical
Qt.TexturePattern 24 Pattern personalizzato

In caso di creazione dell’oggetto QBrush senza parametri, come nel codice di esempio, di default lo stile sarà Qt.NoBrush:

>>> from PyQt5.QtGui import QBrush
>>> brush = QBrush()
>>> brush.style()
0

Nota:

Come nel codice, per vedere personalizzare QBrush è necessario reimplementare il metodo paintEvent().
Per modificare lo stile dopo la creazione dell’oggetto QBrush, si utilizza il metodo setStyle(Qt.BrushStyle):

es.:

...
    def paintEvent(self, event):
        self.painter = QPainter()
        self.painter.begin(self)
        brush = QBrush()
        brush.setStyle(Qt.DiagCrossPattern)
        self.painter.setBrush(brush)
        self.parent().pos()
        self.painter.drawRect(10, 10, 180, 80)
        self.painter.end()
...

BRUSH COLOR

Il colore di default di un oggetto QBrush è il nero.
Per ottenere informazioni sul colore, si utilizza il metodo color():

>>> brush.color()
<PyQt5.QtGui.QColor object at 0x0339F6F0>
>>> brush.color().getRgb()
(0, 0, 0, 255)
>>> brush.color().name()
'#000000'

Per modificare il colore dopo la creazione dell’oggetto QBrush, si utilizza il metodo setColor(QColor):

>>> from PyQt5.QtGui import QColor
>>> new_color = QColor("#FF0000") 
>>> brush.setColor(new_color)
>>> brush.color().name()
'#FF0000'

Nel codice, basterà aggiungere una linea, sempre prima di settare l’oggetto QBrush nel QPainter:

...
    def paintEvent(self, event):
        self.painter = QPainter()
        self.painter.begin(self)
        brush = QBrush()
        brush.setStyle(Qt.DiagCrossPattern)
        new_color = QColor("#FF0000")
        brush.setColor(new_color)
        self.painter.setBrush(brush)
        self.parent().pos()
        self.painter.drawRect(10, 10, 180, 80)
        self.painter.end()
...

Nota:

Come mai il bordo del rettangolo è nero nonostante il colore del brush, sia stato modificato?
QBrush è responsabile del pattern di riempimento della forma/figura disegnata dall’oggetto QPainter, mentre per il contorno di tale forma, è necessario fare riferimento all’oggetto QPen. Modificando il colore del QPen associato al painter, cambierà pertanto il colore della cornice:

...
    def paintEvent(self, event):
        self.painter = QPainter()
        self.painter.begin(self)
        brush = QBrush()
        brush.setStyle(Qt.DiagCrossPattern)
        new_color = QColor("#FF0000")
        brush.setColor(new_color)
        self.painter.setBrush(brush)
        pen = QPen(QColor("Red"))
        pen.setWidth(2)
        self.painter.setPen(pen)
        self.parent().pos()
        self.painter.drawRect(10, 10, 180, 80)
        self.painter.end()
...

BRUSH GRADIENT

Come accennato precedentemente, è possibile sapere che tipo di gradiente viene utilizzato nell’oggetto QBrush, ma non è possibile modificarlo dopo la costruzione dell’oggetto.
Esistono 3 tipi di gradienti: QLinearGradient, QConicalGradient, and QRadialGradient. Si tratta quindi di ereditare da una di queste 3 classi e creare l’ggetto QBrush, con il gradiente personalizzato, passato come argomento.

QLinearGradient

Il gradiente di tipo Linear esegue l’interpolazione dei colori tra due punti, uno iniziale e uno finale. Fuori da questi punti, invece, i colori assegnati sono pieni.
il gradiente può assumere 3 differenti tipi di Spread: Padded, Reflected e Repeated.
Lo spread è il tipo di riempimento utilizzato fuori dall’area del gradiente.
Per conoscere il tipo di spread, si utilizza il metodo spread(), mentre per modificarlo si utilizza il metodo setSpread(spread), dove spread può assumere il valore di uno dei seguenti enum di tipo QGradiant.Spread:

Costante valore descrizione
QGradient.PadSpread 0 Valore di default. L’area è riempita con il colore di “stop” più vicino
QGradient.RepeatSpread 2 Fuori dall’area il gradiente viene ripetuto
QGradient.ReflectSpread 1 Fuori dall’area il gradiente viene riflesso

Per capire come funziona l’interpolazione, useremo i colori bianco e nero.
In sostanza si crea un oggetto gradient ereditando dalla classe prederita delle 3 sopra citate, passando come argomenti, le coordinate dello start point e quelle dell’end point dell’area del gradiente.
Poi si settano il colore di start (Nero) ed il colore di stop (bianco) e si passa l’oggetto gradient al costruttore del QBrush:

from PyQt5.QtGui import QGradient, QLinearGradient

...
    def paintEvent(self, event):
        self.painter = QPainter()
        self.painter.begin(self)
        gradient = QLinearGradient(10, 80, 180, 80)
        gradient.setColorAt(0, QColor("#000000"))
        gradient.setColorAt(1, QColor("#FFFFFF"))
        brush = QBrush(gradient)
        self.painter.setBrush(brush)
        self.parent().pos()
        self.painter.drawRect(10, 10, 180, 80)
        self.painter.end()
...

Le coordinate di start ed end in fase di costruzione dell’oggetto gradient, decidono anche la direzione della linea di interpolazione e la larghezza dell’area che la riguarda.
Se avviciniamo i punti delle coordinate, restringiamo l’area dell’interpolazione:

...
    def paintEvent(self, event):
	...
        gradient = QLinearGradient(80, 80, 100, 80)
...

Se invece di avere la stessa y, le coordinate avranno la stessa x, il gradiente sarà orizzontale invece che verticale:

...
    def paintEvent(self, event):
	...
        gradient = QLinearGradient(50, 20, 50, 80)
...

Giocando sulle coordinate si crea anche un gradiente diagonale:

...
    def paintEvent(self, event):
	...
        gradient = QLinearGradient(50, 20, 50, 80)
...

Queste possibilità, riguardano lo Spread di default, ovvero Qt.PadSpread.
Per cambiare il tipo, si utilizza il setter setSpread(spread), prima di passare l’oggetto gradient al costruttore di QBrush:


...
    def paintEvent(self, event):
        self.painter = QPainter()
        self.painter.begin(self)
        gradient = QLinearGradient(80, 80, 120, 80)
        gradient.setColorAt(0, QColor("#000000"))
        gradient.setColorAt(1, QColor("#FFFFFF"))
        gradient.setSpread(QGradient.RepeatSpread)
        brush = QBrush(gradient)
        self.painter.setBrush(brush)
        self.parent().pos()
        self.painter.drawRect(10, 10, 180, 80)
        self.painter.end()
...

startpoint e endpoint

per conoscere gli start point e gli end point di un oggetto gradient, si utilizzano i metodi start() e finalStop():

>>> from PyQt5.QtGui import QLinearGradient
>>> gradient = QLinearGradient(10, 80, 190, 80)
>>> gradient.start()
PyQt5.QtCore.QPointF(10.0, 80.0)
>>> gradient.finalStop()
PyQt5.QtCore.QPointF(190.0, 80.0)

QRadialGradient

Il gradiente di tipo Radial esegue l’interpolazione dei colori in maniera circolare tra un punto focale ed un end point.
Come per il LinearGradient, i tipi di spread sono sempre Padded, Reflected e Repeated.
Il costruttore del gradient radial, prende come argomenti: le coordinate del centro del cerchio che farà da interpolazione dei colori, il raggio del cerchio e le coordinate del focus.
Per il resto non cambia nulla:

from PyQt5.QtGui import QGradient, QRadialGradient

...
    def paintEvent(self, event):
        self.painter = QPainter()
        self.painter.begin(self)
        gradient = QRadialGradient(50, 50, 50, 80, 80)
        gradient.setColorAt(0, QColor("#000000"))
        gradient.setColorAt(1, QColor("#FFFFFF"))
        brush = QBrush(gradient)
        self.painter.setBrush(brush)
        self.parent().pos()
        self.painter.drawRect(10, 10, 180, 80)
        self.painter.end()
...

Se voglio rimpicciolire il cerchio, agisco sul terzo argomento del costruttore:

from PyQt5.QtGui import QGradient, QRadialGradient

...
    def paintEvent(self, event):
	...
        gradient = QRadialGradient(50, 50, 25, 80, 80)
...

Per spostare il centro del cerchio e le coordinate del focus, ovviamente si dovrà agire sugli altri 4 argomenti.
Con un raggio molto grande, si avrà l’effetto di coprire per intero il rettangolo:

...
    def paintEvent(self, event):
	...
        gradient = QRadialGradient(100, 50, 130, 20, 30)
...

QConicalGradient

Il gradiente di tipo Conical esegue l’interpolazione dei colori con una rotazione oraria attorno ad un punto.
Oltre alle coordinate del punto centrale, è possibile passare al costruttore del gradiente, l’angolo dal quale cominceremo a ruotare.
Come per il LinearGradient, i tipi di spread sono sempre Padded, Reflected e Repeated.

from PyQt5.QtGui import QGradient, QConicalGradient

...
    def paintEvent(self, event):
        self.painter = QPainter()
        self.painter.begin(self)
        gradient = QConicalGradient(50, 50, 45)  # 45 sono i gradi dell'angolo
        gradient.setColorAt(0, QColor("#000000"))
        gradient.setColorAt(1, QColor("#FFFFFF"))
        brush = QBrush(gradient)
        self.painter.setBrush(brush)
        self.parent().pos()
        self.painter.drawRect(10, 10, 180, 80)
        self.painter.end()
...

I parametri del gradiente di tipo Conical, sono recuperabili con gli appositi getter: angle() e center()

>>> from PyQt5.QtGui import QGradient, QConicalGradient
>>> gradient = QConicalGradient(50, 50, 45)
>>> gradient.angle()
45.0
>>> gradient.center()
PyQt5.QtCore.QPointF(50.0, 50.0)

Per modificare tali parametri invece, ci sono gli appositi setter: setAngle(angle) e setCenter(x, y):

>>> gradient.setAngle(55)
>>> gradient.angle()
55.0
>>> gradient.setCenter(60, 60)
>>> gradient.center()
PyQt5.QtCore.QPointF(60.0, 60.0)

BRUSH TEXTURE

Per utilizzare una texture nell’oggetto QBrush, per prima cosa si crea un oggetto QPixmap con l’immagine desiderata, poi lo si passa al costruttore dell’oggetto QBrush.
Una volta creato l’oggetto QBrush, si imposta lo style dello stesso a Qt.TexturePattern.
Oppure si crea l’oggetto QBrush senza argomenti, poi si associa il pixmap con l’apposito setter setTexture(pixmap).
Per sapere quale texture viene utilizzata sul brush, si utilizza il metodo texture():

from PyQt5.QtGui import QPixmap

...

    def paintEvent(self, event):
        self.painter = QPainter()
        self.painter.begin(self)
        pixmap = QPixmap("Qtsmall.png")
        brush = QBrush()
        brush.setStyle(Qt.TexturePattern)
        brush.setTexture(pixmap)
        self.painter.setBrush(brush)
        self.parent().pos()
        self.painter.drawRect(10, 10, 180, 80)
        self.painter.end()
...

Torna all’indice degli appunti

Categorie:PyQt5, python Tag: ,
I commenti sono chiusi.