Рисование в PyQt5

Система рисования PyQt5 способна обрабатывать векторную графику, изображения и шрифты. Рисование необходимо в приложениях, когда мы хотим изменить или улучшить существующий виджет, или мы создаём пользовательский виджет с нуля. Чтобы сделать рисунок, мы используем API рисования, предоставленное инструментарием PyQt5.

Рисование делается в рамках метода paintEvent(). Код рисования размещается между методами begin() и end() объекта QPainter. Он выполняет низкоуровневое рисование на виджетах и других элементах.

Рисование текста

Мы начинаем с рисования Unicode-текста в окне.

#!/usr/bin/python3
# -*- coding: utf-8 -*-

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


class Example(QWidget):

    def __init__(self):
        super().__init__()

        self.initUI()


    def initUI(self):

        self.text = u'\u041b\u0435\u0432 \u041d\u0438\u043a\u043e\u043b\u0430\
\u0435\u0432\u0438\u0447 \u0422\u043e\u043b\u0441\u0442\u043e\u0439: \n\
\u0410\u043d\u043d\u0430 \u041a\u0430\u0440\u0435\u043d\u0438\u043d\u0430'

        self.setGeometry(300, 300, 280, 170)
        self.setWindowTitle('Draw text')
        self.show()


    def paintEvent(self, event):

        qp = QPainter()
        qp.begin(self)
        self.drawText(event, qp)
        qp.end()


    def drawText(self, event, qp):

        qp.setPen(QColor(168, 34, 3))
        qp.setFont(QFont('Decorative', 10))
        qp.drawText(event.rect(), Qt.AlignCenter, self.text)


if __name__ == '__main__':

    app = QApplication(sys.argv)
    ex = Example()
    sys.exit(app.exec_())

В нашем примере, мы рисуем русский текст. Текст выровнен вертикально и горизонтально.

def paintEvent(self, event):
    ...

Рисование делается в пределах paintEvent.

qp = QPainter()
qp.begin(self)
self.drawText(event, qp)
qp.end()

Класс QPainter отвечает за все низкоуровневое рисование. Все методы рисования идут между методами begin() и end().

Фактическое рисование делегируется пользовательскому методу drawText().

qp.setPen(QColor(168, 34, 3))
qp.setFont(QFont('Decorative', 10))

Здесь мы определяем ручку и шрифт, которые используются, чтобы рисовать текст.

qp.drawText(event.rect(), Qt.AlignCenter, self.text)

Метод drawText() рисует текст в окне. Метод rect() события рисования возвращает прямоугольник, который должен быть обновлён.

Рисование текста

Рисование точек

Точка – это самый простой графический объект, который может быть нарисован. Это маленькое пятнышко в окне.

#!/usr/bin/python3
# -*- coding: utf-8 -*-

import sys, random
from PyQt5.QtWidgets import QWidget, QApplication
from PyQt5.QtGui import QPainter, QColor, QPen
from PyQt5.QtCore import Qt


class Example(QWidget):

    def __init__(self):
        super().__init__()

        self.initUI()


    def initUI(self):

        self.setGeometry(300, 300, 280, 170)
        self.setWindowTitle('Points')
        self.show()


    def paintEvent(self, e):

        qp = QPainter()
        qp.begin(self)
        self.drawPoints(qp)
        qp.end()


    def drawPoints(self, qp):

        qp.setPen(Qt.red)
        size = self.size()

        for i in range(1000):
            x = random.randint(1, size.width()-1)
            y = random.randint(1, size.height()-1)
            qp.drawPoint(x, y)


if __name__ == '__main__':

    app = QApplication(sys.argv)
    ex = Example()
    sys.exit(app.exec_())

В нашем примере, мы произвольным образом рисуем 1000 красных точек в окне.

qp.setPen(Qt.red)

Мы устанавливаем ручку красного цвета. Мы используем предопределённую цветовую константу Qt.red.

size = self.size()

Каждый раз, когда мы меняем размер окна, вызывается paintEvent. Мы получаем текущий размер окна с помощью метода size(). Мы используем размер окна, чтобы распределять точки по всему окну.

qp.drawPoint(x, y)

Мы рисуем точку с помощью метода drawPoint().

Точки

Цвета

Цвет – это объект, представляющий собой комбинацию красного, зелёного и синего (RGB) значений интенсивности. Корректные значения RGB находятся в диапазоне от 0 до 255. Мы можем определить цвет разными способами. Самый распространённый – десятичные или шестнадцатеричные значения RGB. Мы также можем использовать значения RGBA, которые обозначают красный, зелёный, синий и альфа-канал. Здесь мы добавляем немного дополнительной информации относительно прозрачности. Значение альфа 255 определяет полную непрозрачность, 0 – полная прозрачность, т.е. цвет невидим.

#!/usr/bin/python3
# -*- coding: utf-8 -*-

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


class Example(QWidget):

    def __init__(self):
        super().__init__()

        self.initUI()


    def initUI(self):

        self.setGeometry(300, 300, 350, 100)
        self.setWindowTitle('Colours')
        self.show()


    def paintEvent(self, e):

        qp = QPainter()
        qp.begin(self)
        self.drawRectangles(qp)
        qp.end()


    def drawRectangles(self, qp):

        col = QColor(0, 0, 0)
        col.setNamedColor('#d4d4d4')
        qp.setPen(col)

        qp.setBrush(QColor(200, 0, 0))
        qp.drawRect(10, 15, 90, 60)

        qp.setBrush(QColor(255, 80, 0, 160))
        qp.drawRect(130, 15, 90, 60)

        qp.setBrush(QColor(25, 0, 90, 200))
        qp.drawRect(250, 15, 90, 60)


if __name__ == '__main__':

    app = QApplication(sys.argv)
    ex = Example()
    sys.exit(app.exec_())

В нашем примере, мы рисуем 3 окрашенных прямоугольника.

color = QColor(0, 0, 0)
color.setNamedColor('#d4d4d4')

Здесь мы определяем цвет, используя шестнадцатеричную систему счисления.

qp.setBrush(QColor(200, 0, 0))
qp.drawRect(10, 15, 90, 60)

Здесь мы определяем кисть и рисуем прямоугольник. Кисть – это элементарный графический объект, который используется, чтобы рисовать фон очертания. Метод drawRect() принимает четыре параметра. Первые два – значения x и y на осях. Третий и четвёртый параметры – ширина и высота прямоугольника. Метод рисует прямоугольник, используя текущие ручку и кисть.

Цвета

QPen

QPen (ручка) – это элементарный графический объект. Он используется, чтобы рисовать линии, кривые и контуры прямоугольников, эллипсов, многоугольников и других фигур.

#!/usr/bin/python3
# -*- coding: utf-8 -*-

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


class Example(QWidget):

    def __init__(self):
        super().__init__()

        self.initUI()


    def initUI(self):

        self.setGeometry(300, 300, 280, 270)
        self.setWindowTitle('Pen styles')
        self.show()


    def paintEvent(self, e):

        qp = QPainter()
        qp.begin(self)
        self.drawLines(qp)
        qp.end()


    def drawLines(self, qp):

        pen = QPen(Qt.black, 2, Qt.SolidLine)

        qp.setPen(pen)
        qp.drawLine(20, 40, 250, 40)

        pen.setStyle(Qt.DashLine)
        qp.setPen(pen)
        qp.drawLine(20, 80, 250, 80)

        pen.setStyle(Qt.DashDotLine)
        qp.setPen(pen)
        qp.drawLine(20, 120, 250, 120)

        pen.setStyle(Qt.DotLine)
        qp.setPen(pen)
        qp.drawLine(20, 160, 250, 160)

        pen.setStyle(Qt.DashDotDotLine)
        qp.setPen(pen)
        qp.drawLine(20, 200, 250, 200)

        pen.setStyle(Qt.CustomDashLine)
        pen.setDashPattern([1, 4, 5, 4])
        qp.setPen(pen)
        qp.drawLine(20, 240, 250, 240)


if __name__ == '__main__':

    app = QApplication(sys.argv)
    ex = Example()
    sys.exit(app.exec_())

В нашем примере, мы рисуем шесть линий. Линии рисуются в шести разных стилях ручки. Существует пять предопределённых стилей QPen. Мы также можем создать пользовательские стили. Последняя линия нарисована с использованием пользовательского стиля.

pen = QPen(Qt.black, 2, Qt.SolidLine)

Мы создаём объект QPen. Цвет – чёрный. Ширина устанавливается в 2 пикселя так, чтобы мы могли видеть различия между стилями ручки. Qt.SolidLine – это один из предопределённых стилей (жирная линия).

pen.setStyle(Qt.CustomDashLine)
pen.setDashPattern([1, 4, 5, 4])
qp.setPen(pen)

Здесь мы определяем пользовательский стиль ручки. Мы устанавливаем стиль ручки Qt.CustomDashLine и вызываем метод setDashPattern(). Список чисел определяет стиль. Может быть даже несколько чисел. Нечётные числа определяют сплошную линию, чётные числа – промежутки. Чем больше число, тем больше промежуток или штрих. Наш образец – штрих в 1 пиксель, промежуток в 4 пикселя, штрих в 5 пикселей, промежуток в 4 пикселя, и т.д.

То, что получилось, хорошо видно на картинке.

Стили ручки

QBrush

QBrush – это элементарный графический объект. Он используется для рисования фона графических форм, таких как прямоугольники, эллипсы или многоугольники. Кисть может быть трёх разных типов: предопределённая кисть, градиент, образец текстуры.

#!/usr/bin/python3
# -*- coding: utf-8 -*-

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


class Example(QWidget):

    def __init__(self):
        super().__init__()

        self.initUI()


    def initUI(self):

        self.setGeometry(300, 300, 355, 280)
        self.setWindowTitle('Brushes')
        self.show()


    def paintEvent(self, e):

        qp = QPainter()
        qp.begin(self)
        self.drawBrushes(qp)
        qp.end()


    def drawBrushes(self, qp):

        brush = QBrush(Qt.SolidPattern)
        qp.setBrush(brush)
        qp.drawRect(10, 15, 90, 60)

        brush.setStyle(Qt.Dense1Pattern)
        qp.setBrush(brush)
        qp.drawRect(130, 15, 90, 60)

        brush.setStyle(Qt.Dense2Pattern)
        qp.setBrush(brush)
        qp.drawRect(250, 15, 90, 60)

        brush.setStyle(Qt.Dense3Pattern)
        qp.setBrush(brush)
        qp.drawRect(10, 105, 90, 60)

        brush.setStyle(Qt.DiagCrossPattern)
        qp.setBrush(brush)
        qp.drawRect(10, 105, 90, 60)

        brush.setStyle(Qt.Dense5Pattern)
        qp.setBrush(brush)
        qp.drawRect(130, 105, 90, 60)

        brush.setStyle(Qt.Dense6Pattern)
        qp.setBrush(brush)
        qp.drawRect(250, 105, 90, 60)

        brush.setStyle(Qt.HorPattern)
        qp.setBrush(brush)
        qp.drawRect(10, 195, 90, 60)

        brush.setStyle(Qt.VerPattern)
        qp.setBrush(brush)
        qp.drawRect(130, 195, 90, 60)

        brush.setStyle(Qt.BDiagPattern)
        qp.setBrush(brush)
        qp.drawRect(250, 195, 90, 60)


if __name__ == '__main__':

    app = QApplication(sys.argv)
    ex = Example()
    sys.exit(app.exec_())

В нашем примере, мы рисуем девять разных прямоугольников.

brush = QBrush(Qt.SolidPattern)
qp.setBrush(brush)
qp.drawRect(10, 15, 90, 60)

Мы определяем объект кисти. Мы устанавливаем его в объект рисования и рисуем прямоугольник с помощью метода drawRect().

Кисти

В этой части руководства PyQt5, мы рассмотрели некоторые основы рисования.

Обсуждение вопросов, не связанных со статьёй (в т.ч. комментарии типа "Помогите!"), ведётся на форуме pythonworld.club, а не в комментариях.

Для вставки кода на Python в комментарий заключайте его в теги <pre><code class="python3">Ваш код</code></pre>
Опечатка в тексте:
Послать сообщение об ошибке автору?