Доброго здоровья читателям моего канала programmer's notes. Поддерживаем мой канал.
Объекты QPixmap и QImage в PyQt5
Изучив ещё раз раз свой канал, я совершенно чётко увидел несколько тем, которые освящены плохо. Конечно это графика. Хотя статьи по графике и есть. Но, как минимум, по трём библиотекам желательно добавить статьи. Сегодня будет продолжение графики вот этой статьи. В ней показан один из возможных алгоритмов рисования с помощью мыши. Естественно возникает вопрос: а как сохранить картинку, которую вы нарисовали. Я несколько переделал алгоритм, но идеологию оставил прежнюю. Поэтому мне пришлось несколько подстраиваться под эту идеологию. По этой причине объект класса QImage будет использоваться, как вспомогательный, а не основной инструмент. Но в будущем я рассмотрю и другой вариант подобного "редактора". Конечно, это очень простой редактор, но мне важна идея, а её можно развивать. Указанную выше статью, надо бы посмотреть, хотя сегодняшнюю программу, я постараюсь тоже хорошо прокомментировать. Да, нужно вспомнить про стандартные диалоговые окна. Например, почитать в моей статье здесь.
Программа, которая представлена ниже, проста (см. Рисунок 2). Двойной щелчок мыши и можно рисовать. Ещё один двойной щелчок - выход из режима рисования. Ctrl+s - сохранить рисунок в указанный файл.
Программа представлена ниже, см. Рисунок 1.
Пояснения к программе
- Список self.vcp хранит точки, определяющие нарисованную линию. Каждый элемент массива состоит из трех компонент: две координаты и признак того, что это последняя точка непрерывной линии (значение 0, не последняя точка, значение 1 - последняя).
- Переменная self.f равна 1, если мышью можно рисовать и 0, если рисовать нельзя.
- Идея редактора заключается в том, что при движении мыши в режиме рисования точки, по которым проходит курсор мыши, заносятся в массив self.vcp и сразу вызывается процедура paintEvent() для перерисовки. Для этого используется метод self.update().
- В процедуре paintEvent() создаётся объект класса QPainter, основного класса для рисования. Далее создаётся перо setPen() с указанием ширины и цвета (QColor()). Само рисование происходит между методами begin() и end(). Рисование в нашем случае заключается в соединении соседних точек (метод drawLine()) по всему массиву self.vcp.
- Метод mouseMoveEvent() отслеживает движение мыши и если self.f равен 1, заносить координаты в массив self.vcp.
- Метод mouseDoubleClickEvent() срабатывает при двойном щелчке левой кнопкой мыши. Происходит переключение из состояния рисования в состояние не рисования и обратно. Если мы выходим из состояния рисования, то помечаем последнюю точку, чтобы от неё потом не шла линия.
- Метод mouseReleaseEvent() срабатывает, когда отпускается клавиша мыши. В программе отрабатывается отпускание правой кнопки мыши. Из массива self.vcp удаляется последняя точка, а новая последняя точка помечается как последняя. Для перерисовки вызывается метод update(). При этом учитываем, в каком состоянии находится программа, если в состоянии рисования, то нажатие не учитывается.
- Для сохранения изображения используется сочетание ctrl+s. Для этого применяется метод keyPressEvent(). Проверяется нажата ли s и потом нажат ли ctrl. Также учитывается значение self.f. При нажатии вызывается метод self.sv().
- Для получения имени файла, куда нужно будет сохранить картинку, используем класс QFileDialog и метод getSaveFileName().
- Далее интересное. С помощью метода grab() получаем пиксельную копию окна (объект класса QPixmap). Далее с помощью метода toImage() получаем объект класса QImage. После чего уже можно создавать файл-картинку с помощью метода save().
Замечание 1.
Подход, представленный в программе не слишком хорош. Мы работаем со всем окном, а там надо разместить и меню и кнопки. Это мешает сделать из программы полноценный графический редактор. Поэтому в будущем мы посмотрим, как усовершенствовать подход, если использовать в окне объект QImage.
Замечание 2.
Ещё один важный момент. По сути мы используем так называем векторный подход, т.е. храним изображения в виде последовательности объектов (в нашем случае точек). Но сохраняем через QImage весь образ окна. Рациональнее было бы хранить всё в виде файла-содержащего массив self.vcp. И к этому вопросу мы тоже вернёмся в одной из следующих статей.
Пока всё!
Хорошего программирования. Оставляйте свои комментарии, не забывайте про лайки и подписывайтесь на мой канал programmer's notes.