Меню
Видеоучебник

Рисование на форме

Урок 32. Основы алгоритмизации и программирования на языке Python

На этом уроке ученики узнают, для чего нужно рисование при создании приложений с графическим интерфейсом, какие классы описаны для рисования в графической библиотеке PyQt5 и как запрограммировать рисование.

Конспект урока "Рисование на форме"

Вопросы:

·     Зачем нужно рисование при создании графического интерфейса программы?

·     Инструменты для рисования в PyQt5.

·     Программирование рисования.

Наверняка, как только вы услышали тему урока, у некоторых из вас возник вопрос: «Какое отношение имеет рисование к программированию?». Если речь идёт о графическом интерфейсе, то он управляется с помощью виджетов. Классы для наиболее распространённых виджетов уже описаны в графической библиотеке. Все эти виджеты имеют свой внешний вид, который уже давно изображён. Но как быть, если в графической библиотеке не найдётся нужного нам виджета? Тогда нам понадобится описать его самостоятельно. В описание входит и внешний вид виджета. Здесь-то нам и понадобится рисование. Помимо этого, рисование в приложениях с графическим интерфейсом имеет ещё множество применений. Например, если нам понадобится построить график функции или же описать работу какой-нибудь модели, мы также будем использовать средства рисования. Рисовать можно в окне программы и на виджетах.

Посмотрим, что нужно сделать для того, чтобы начать рисовать. Как видим, в нашем модуле уже описаны команды для запуска приложения, а также начато описание класса MainWindow – наследника класса QWidget. Этот класс будет описывать работу главного окна программы. У него уже описан конструктор.

import sys

from PyQt5.QtWidgets import QWidget, QApplication

 

class MainWindow (QWidget):

    def __init__ (self):

        super ().__init__ ()

        self.setWindowTitle ('Рисование в PyQt5')

        self.setFixedSize (400, 400)

        self.move (540, 270)

 

a = QApplication (sys.argv)

window = MainWindow ()

window.show ()

sys.exit (a.exec ())

Чтобы начать рисовать на форме окна программы, нужно в классе этого окна переопределить метод paintEvent, описанный у его предка – класса QWidget. Этот метод отвечает за рисование. В методе нужно создать объект класса QPainter, отвечающий за низкоуровневое рисование. Этот класс, как и другие классы для рисования, описан в модуле QtGui. Загрузим из этого модуля все классы, так как мы пока не знаем, какие ещё классы нам понадобятся. Также загрузим из модуля QtCore класс Qt.

from PyQt5.QtGui import *

from PyQt5.QtCore import Qt

Создадим в переменной pnt объект класса QPainter. Далее у этого объекта по порядку вызываются методы begin с параметром self и end без параметров. Между вызовами этих методов описываются все команды для рисования.

Для начала рассмотрим рисование текста. Для этого вызовем пользовательский метод, который назовём paint. Его мы опишем позже. Он будет принимать на вход ссылку на событие, вызвавшее метод paintEvent, то есть event, а также ссылку на созданный объект класса QPainter, то есть pnt.

def paintEvent (self, event):

    pnt = QPainter ()

    pnt.begin (self)

    self.Paint (event, pnt)

    pnt.end ()

Теперь в классе нашего окна опишем метод Paint. Напомним, что он должен принимать на вход ссылку на событие, которое так же, как и в прошлом методе, назовём event, а также ссылку на объект класса QPainter, который так же назовём pnt. Вызовем у объекта pnt метод setPen, в котором укажем цвет нашего текста. Для этого вызовем конструктор класса QColor, который формирует цвет по цветовой модели RGB. Он принимает на вход количества цветовых параметров модели, то есть красного, синего и зелёного цветов соответственно. Установим красный цвет. Для этого зададим числа двести пятьдесят пять, ноль и ноль. Далее нам нужно задать шрифт текста. Для этого у объекта pnt вызовем метод setFont. А в нём, в свою очередь, – конструктор класса QFont. Он создаёт модель шрифта и принимает на вход два параметра: текстовую строку, в которой задано название шрифта, и целое число – размер шрифта в пунктах. Зададим шрифт Times New Roman величиной 20 пунктов. И, наконец, вызовем у объекта pnt метод drawText. В нём мы должны задать прямоугольник, в котором будет изображён текст. Чтобы его создать, у события вызовем метод Rect без параметров. Далее мы должны задать выравнивание текста. Выберем выравнивание по центру. Для этого укажем значение Align.Center из класса Qt. Теперь нам нужно задать сам текст в виде символьной строки. Пусть он будет таким: «Мама мыла раму».

def Paint (self, event, pnt):

        pnt.setPen (QColor (255, 0, 0))

        pnt.setFont (QFont ('Times New Roman', 20))

        pnt.drawText (event.rect (), Qt.AlignCenter, 'Мама мыла раму.')

Запустим программу на выполнение. На экран было выведено окно программы, в котором красными буквами написан текст «Мама мыла раму». Именно этот текст мы и задали.

В классе QPainter описаны методы для рисования некоторых геометрических фигур. Их имена начинаются со слова «draw». Для рисования точки используется метод drawPoint, который принимает на вход два целых числа – координаты точки в пикселях. Для рисования линии используется метод drawLine. Он принимает на вход координаты начальной и конечной точек линии. Для рисования прямоугольника используется метод drawRect, который принимает на вход четыре целых числа: координаты левого верхнего угла прямоугольника, а также его ширину и высоту. Для рисования эллипса используется метод drawEllipse, который принимает на вход 4 целых числа – параметры прямоугольника, в который эллипс будет вписан.

В классе QPainter есть два основных инструмента для рисования: ручка и кисть. Ручка используется для рисования текста, точек, линий и контуров фигур. Она задаётся объектом класса QPen. Кисть используется для рисования фона фигур. Она задаётся объектом класса QBrush. Ручка и кисть задаются для объекта QPainter с помощью методов setPen и setBrush соответственно.

Рассмотрим инструмент «Ручка». Конструктор класса QPen принимает на вход не более трёх аргументов: первый из них – цвет ручки, он может быть задан с помощью объекта класса QColor. Второй аргумент – это целое число, которое означает толщину линии в пикселях. И третий аргумент – это стиль линии. Один или несколько аргументов могут отсутствовать. В этом случае по умолчанию у ручки чёрный цвет и толщина линии равна одному пикселю. И если с цветом и толщиной линии всё понятно, то со стилем линии не всё так просто. Всего есть пять стилей линий. Они описаны в классе Qt.

Рассмотрим, как выглядят разные типы линий, нарисовав их. Для этого уберём весь код из метода Paint. Теперь создадим в нём, в переменной pen, объект класса QPen, в котором зададим параметры ручки. Пусть цвет ручки будет синим, то есть его можно задать числами ноль, ноль и двести пятьдесят пять. Установим толщину линии равной трём пикселям, а стиль линии пока задавать не будем. Дальше будем устанавливать ручке разные стили линий и будем рисовать эти линии.  Задать стиль ручки после того, как она была создана, можно с помощью метода setStyle. Установим стиль SolidLine. Теперь вызовем у объекта pnt метод setPen, в котором зададим ему созданную нами ручку – pen. Теперь осталось лишь изобразить линию. Для этого у объекта pnt вызовем метод drawLine. Проведём первую линию из точки с координатами двадцать, пятьдесят в точку с координатами 380, 50. Теперь скопируем три последние строки кода. Изменим стиль новой линии на DashLine и разместим её на 60 ниже предыдущей. Точно так же зададим линии и с оставшимися тремя стилями.

def Paint (self, event, pnt):

    pen = QPen (QColor (0, 0, 255), 3)

 

    pen.setStyle (Qt.SolidLine)

    pnt.setPen (pen)

    pnt.drawLine (20, 50, 380, 50)

 

    pen.setStyle (Qt.DashLine)

    pnt.setPen (pen)

    pnt.drawLine (20, 110, 380, 110)

 

    pen.setStyle (Qt.DotLine)

    pnt.setPen (pen)

    pnt.drawLine (20, 170, 380, 170)

 

    pen.setStyle (Qt.DashDotLine)

    pnt.setPen (pen)

    pnt.drawLine (20, 230, 380, 230)

 

    pen.setStyle (Qt.DashDotDotLine)

    pnt.setPen (pen)

    pnt.drawLine (20, 290, 380, 290)

Сохраним модуль и запустим его на выполнение. На экран была выведена форма с линиями различных стилей. Мы можем рассмотреть их.

Однако вы можете заметить, что внизу формы есть место для ещё одной линии. Мы оставили его не просто так. Дело в том, что мы можем создать собственный стиль линии. Для этого ещё раз скопируем код, в котором мы задаём стиль линии для ручки, и нарисуем этой ручкой линию. Зададим линии стиль CustomDashLine. Это пользовательский стиль. Чтобы его задать, вызовем у объекта pen метод setDashPattern. Он позволяет задать штриховой шаблон с помощью списка целых чисел, в котором числа с нечётными порядковыми номерами задают длины штрихов, а с чётными – длины промежутков. Зададим длины штрихов равными 1, 3, 5 и 7 пикселям соответственно, а длины промежутков – по 2 пикселя. Нарисуем эту линию на шестьдесят пикселей ниже предыдущей.

pen.setStyle (Qt.CustomDashLine)

pen.setDashPattern ([1, 2, 3, 2, 5, 2, 7, 2])

pnt.setPen (pen)

pnt.drawLine (20, 350, 380, 350)

Снова запустим модуль на выполнение. На этот раз на форме стало на одну линию больше. Причём новая линия полностью соответствует шаблону, который мы задали.

Мы рассмотрели, как задаётся ручка. Теперь рассмотрим, как задаётся кисть для рисования фонов фигур. Конструктор класса QBrush принимает на вход 2 аргумента: цвет кисти и стиль кисти. По умолчанию у кисти чёрный цвет, а стиль – сплошной цвет. У кисти есть множество стилей. Вот наиболее распространённые из них.

По умолчанию у кисти устанавливается стиль SolidPattern. Если нужно установить кисть, которая не будет закрашивать фигуры, то у неё устанавливается стиль NoBrush. Если нужно установить интенсивность цвета, то в нашем распоряжении стили DensePattern с номерами 1-7. С увеличением номера интенсивность цвета уменьшается.

Создадим кисть, после чего поэкспериментируем со стилями, изобразив несколько геометрических фигур. Уберём из метода Paint весь код, за исключением того, в котором мы создали ручку и задали её объекту pnt. Этой ручкой будут рисоваться контуры наших фигур. В переменной brush создадим объект класса QBrush. Зададим красный цвет кисти, а стиль пока указывать не будем. Его установим, вызвав у объекта brush метод setStyle. Выберем шаблон стиля SolidPattern. Теперь вызовем у объекта pnt метод setBrush, в котором зададим ему созданную нами кисть. Теперь изобразим прямоугольник, вызвав у объекта pnt метод drawRect. Установим левый верхний угол прямоугольника в точку 30, 20, а размеры прямоугольника – 100´80. Теперь скопируем последние три строки кода и изменим их для изображения эллипса с теми же параметрами, что и у прямоугольника, но на сто двадцать пикселей правее и со стилем заливки Dense4Pattern. Ещё на сто двадцать пикселей левее изобразим прямоугольник с теми же параметрами и стилем заливки NoBrush. Скопируем код для рисования первых трёх фигур и изменим его для рисования на сто пикселей ниже такого же ряда фигур, но с другими стилями заливки.

def Paint (self, event, pnt):

    pen = QPen (QColor (0, 0, 255), 3)

    pen.setStyle (Qt.SolidLine)

    pnt.setPen (pen)

    brush = QBrush (QColor (255, 0, 0))

 

    brush.setStyle (Qt.SolidPattern)

    pnt.setBrush (brush)

    pnt.drawRect (30, 20, 100, 80)

 

    brush.setStyle (Qt.Dense4Pattern)

    pnt.setBrush (brush)

    pnt.drawEllipse (150, 20, 100, 80)

 

    brush.setStyle (Qt.NoBrush)

    pnt.setBrush (brush)

    pnt.drawRect (270, 20, 100, 80)

 

    brush.setStyle (Qt.HorPattern)

    pnt.setBrush (brush)

    pnt.drawRect (30, 160, 100, 80)

 

    brush.setStyle (Qt.VerPattern)

    pnt.setBrush (brush)

    pnt.drawEllipse (150, 160, 100, 80)

 

    brush.setStyle (Qt.BDiagPattern)

    pnt.setBrush (brush)

    pnt.drawRect (270, 160, 100, 80)

 

    brush.setStyle (Qt.FDiagPattern)

    pnt.setBrush (brush)

    pnt.drawRect (30, 300, 100, 80)

 

    brush.setStyle (Qt.CrossPattern)

    pnt.setBrush (brush)

    pnt.drawEllipse (150, 300, 100, 80)

 

    brush.setStyle (Qt.DiagCrossPattern)

    pnt.setBrush (brush)

    pnt.drawRect (270, 300, 100, 80)

После того, как мы нарисовали все фигуры, сохраним модуль и запустим его на выполнение. На экране появилось окно, на котором изображено девять геометрических фигур с различными стилями заливки. Теперь мы можем наглядно сравнить стили кисти между собой.

Мы узнали:

·     Для рисования на форме нужно переопределить у неё метод paintEvent, описанный в классе QWidget. В этом методе нужно создать объект класса QPainter. Между вызовами у этого объекта методов begin и end задаются все команды для рисования.

·     Инструмент QPen используется для рисования текста, линий, точек и контуров геометрических фигур.

·     Инструмент QBrush используется для рисования фона геометрических фигур.

·     В классе QPainter описан ряд методов для рисования: метод drawText – для рисования текста, drawPoint – для рисования точки, drawLine – для линии, drawRect – для прямоугольника, drawEllipse – для эллипса.

0
2073

Комментарии 0

Чтобы добавить комментарий зарегистрируйтесь или на сайт

Вы смотрели