Телефон: 8-800-350-22-65
WhatsApp: 8-800-350-22-65
Telegram: sibac
Прием заявок круглосуточно
График работы офиса: с 9.00 до 18.00 Нск (5.00 - 14.00 Мск)

Статья опубликована в рамках: LXXXVIII Международной научно-практической конференции «Научное сообщество студентов XXI столетия. ТЕХНИЧЕСКИЕ НАУКИ» (Россия, г. Новосибирск, 09 апреля 2020 г.)

Наука: Информационные технологии

Скачать книгу(-и): Сборник статей конференции

Библиографическое описание:
Зубов С.В. РАЗРАБОТКА МОДУЛЬНОГО ГРАФИЧЕСКОГО РЕДАКТОРА YAMIE НА ЯЗЫКЕ ПРОГРАММИРОВАНИЯ PYTHON // Научное сообщество студентов XXI столетия. ТЕХНИЧЕСКИЕ НАУКИ: сб. ст. по мат. LXXXVIII междунар. студ. науч.-практ. конф. № 4(87). URL: https://sibac.info/archive/technic/4(87).pdf (дата обращения: 13.05.2024)
Проголосовать за статью
Конференция завершена
Эта статья набрала 0 голосов
Дипломы участников
У данной статьи нет
дипломов

РАЗРАБОТКА МОДУЛЬНОГО ГРАФИЧЕСКОГО РЕДАКТОРА YAMIE НА ЯЗЫКЕ ПРОГРАММИРОВАНИЯ PYTHON

Зубов Святослав Владимирович

студент 2 курса, факультет прикладной космонавтики и фотограмметрии, Московский государственный университет геодезии и картографии (МИИГАиК),

РФ, г. Москва

Лапчинская Маргарита Петровна

научный руководитель,

канд. техн. наук, доц., Московский государственный университет геодезии и картографии (МИИГАиК),

РФ, г. Москва

DEVELOPMENT OF THE MODULAR GRAPHICS EDITOR YAMIE IN THE PYTHON PROGRAMMING LANGUAGE

 

Svyatoslav V. Zubov

second-year student, Faculty of Applied Cosmonautics and Photogrammetry, Moscow state university of geodesy and cartography (MIIGAiK),

Russia, Moscow

Margarita P. Lapchinskaya

scientific director, сandidate of Science, assistant professor, Moscow state university of geodesy and cartography (MIIGAiK)

Russia, Moscow

 

АННОТАЦИЯ

В данной статье поэтапно описывается разработка модульного графического редактора YAMIE с использованием языка программирования Python 3, GUI-тулкита Qt 5 и его биндингов (привязок) для Python – PyQt5.

Особенностью YAMIE является то, что он состоит из так называемого ядра и модулей. Основными функциями ядра являются загрузка, отображение и сохранение изображения, а также загрузка модулей, предназначенных для расширения функционала программы.

Исходный код разработанного графического редактора расположен на ресурсе [1]. Программа распространяется по лицензии GNU GPL v3.

ABSTRACT

This article describes step-by-step development of modular graphics editor called “YAMIE” using Python 3 programming language, Qt 5 GUI toolkit and its bindings for Python – PyQt5.

Main feature of YAMIE is following architecture: YAMIE is divided into so-called core and plugins. Loading, displaying and saving are the main functionality of the core. The core also loads plugins, created to enhance functionality of the program.

Source code of YAMIE can be found on resource [1]. The program is being distributed under the GNU GPL v3 license.

 

Ключевые слова: программирование, модульное программирование, разработка ПО, Python, Python 3, Qt, Qt5, PyQt, PyQt5, графический редактор, YAMIE.

Keywords: programming, modular programming, software development, Python, Python 3, Qt, Qt5, PyQt, PyQt5, graphics editor, YAMIE.

 

Введение

Модульное программирование – это организация разработки программного обеспечения, которая подразумевает разделение функциональности программы на независимые взаимозаменяемые модули, каждый из которых содержит все необходимое для выполнения только одного аспекта желаемой функциональности [2].

Модульное программирование связано со структурным и объектно-ориентированным программированием – все эти парадигмы преследуют цель облегчения создания крупных программ путем разложения их на более мелкие части.

Модуль – это функционально законченный фрагмент программы. Во многих языках (но далеко не обязательно) оформляется в виде отдельного файла с исходным кодом или поименованной непрерывной её части. Некоторые языки, включая Python, предусматривают объединение модулей в пакеты [3].

Преимущества модульной архитектуры:

  • повторное использование кода модуля;
  • обновление и замена модуля без необходимости изменения остальной системы;
  • уменьшение времени компиляции при изменении модуля (модули компилируются отдельно)
  • Упрощение групповой разработки (модули можно создавать и тестировать отдельно от остальной системы)

Python – это широко используемый интерпретируемый высокоуровневый язык программирования общего назначения, основными преимуществами которого являются [4]:

  • читаемость кода, где, в частности, используются отступы в виде пробелов для разделения блоков кода, а не фигурные скобки или ключевые слова;
  • синтаксис, позволяющий программистам разрабатывать программы с использованием меньшего количества строк кода, чем это могло быть с использованием таких языков, как C++ или Java [5];
  • динамическая типизация и автоматическое управление памятью.

Интерпретаторы Python доступны на многих операционных системах. Эталонной реализацией Python является интерпретатор CPython, поддерживающий большинство активно используемых платформ. Он распространяется под свободной лицензией Python Software Foundation License, позволяющей использовать его без ограничений в любых приложениях, включая проприетарные.

Существуют реализации Python для Java Virtual Machine (виртуальная машина, в которой выполняется код на Java), Common Intermediate Language (язык, в который транслируется код на .NET), LLVM (набор компиляторов) и других технологий. Проект PyPy предлагает JIT-компилятор Python, который значительно увеличивает скорость выполнения Python-программ. [4]

1. Разработка графического редактора YAMIE

Функциональные элементы программы и структура проекта представлены в таблицах 1 и 2 соответственно:

Таблица 1. 

Функциональные элементы программы

Элемент программы

Функциональное назначение

Ядро

Загрузка, сохранение и отображение изображений

Отображение пользовательского интерфейса (ui файла)

Загрузка модулей

ui-файл

Разметка пользовательского интерфейса

Модули

Дополнение функциональности программы с помощью модулей

 

Таблица 2.

Структура проекта

Файл/директория

Описание

YAMIE.py

Ядро

ui

Директория с файлами разметки интерфейса

ui/mainwindow.ui

Файл разметки главного окна

plugins

Директория, в которой находятся модули

plugins/plugins.cfg

Файл со списком плагинов для загрузки

 

Для запуска программы необходимо запустить файл YAMIE.py. В данной статье опускается сборка бинарных файлов и разработка установочных скриптов для различных ОС.

Стандартные и пользовательские модули находятся в директории plugins. Чтобы программа загружала модуль, достаточно написать имя его файла (без расширения с соблюдением регистра) в файле plugins/plugins.cfg с новой строки (одна строчка – один модуль). Чтобы выключить модуль, можно удалить его название из файла или добавить символ # в начале строки.

Разработка программы состоит из следующих этапов:

  • Этап 1 – Проектирование интерфейса;
  • Этап 2 – Разработка ядра;
  • Этап 3 – Разработка модулей для YAMIE.

1.1. Проектирование интерфейса

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

На рис.1 представлена форма программы в Qt Designer (тему UX-дизайна и написания разметки элементов опускаем):

 

Рисунок 1. Форма программы в Qt Designer

 

Для более наглядного внешнего вида в дальнейшем после добавления плагинов на панель будет добавлен горизонтальный разделитель – Horizontal Spacer. Если сделать это сейчас, то виджеты модулей будут находиться на правой стороне. При большом количестве модулей они будут образовывать неразрывную линию, поэтому будет логичнее расположить все элементы управления на левой стороне.

Организуется разметка виджетов, которую можно увидеть в разделе «Object Inspector» в Qt Designer – рис.2:

 

Рисунок 2. Раздел «Object Instector» в Qt Designer

 

Функциональное назначение используемых виджетов представлено в таблице 3:

Таблица 3. 

Функциональное назначение виджетов

Виджет

Функциональное назначение

MainWindow

Окно программы

layoutOnTop

Панель, содержащая кнопки загрузки и сохранения и виджеты модулей

buttonOpen

Кнопка загрузки изображения

buttonSave

Кнопка сохранения изображения

divider

Линия, разделяющая кнопки загрузки и сохранения от виджетов модулей

Image

Изображение (в Qt для отображения изображений используют надписи)

 

Данный этап завершается сохранением форму в каталог ui с именем файла mainwindow.ui.

1.2. Разработка ядра

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

Второй этап состоит из выполнения следующих действий:

1. Импортирование необходимых пакетов:

import sys

# For recursive module import

import importlib

# For creating instances of Qt widgets

from PyQt5.QtWidgets import QApplication, QMainWindow, QFileDialog, QMessageBox

# For creating pixmaps

from PyQt5.QtGui import QPixmap, QImage

# For loading ui file

from PyQt5 import uic

2. Инициализация класса окна программы и загрузка файла разметки интерфейса в конструкторе окна:

# Main window of application

 

class Window(QMainWindow):

 

    # Initialize application

    def __init__(self):

 

    # Make our app super awesome

    super().__init__()

    # Load UI from file

    uic.loadUi('ui/mainwindow.ui', self)

3. После инициализации класса окна создается экземпляр QApplication, экземпляр класса окна, и отображается само окно программы:

if __name__ == '__main__':

    # Create an instance of QApplication

    app = QApplication(sys.argv)

    # Create an instance of our Window class

    window = Window()

    # Show window

    window.show()

    # Execute app and also write action for exiting

    sys.exit(app.exec_())

4. В конструкторе окна подключаются события по нажатию кнопок загрузки и сохранения изображения.

self.buttonOpen.clicked.connect(self.onOpen)

self.buttonSave.clicked.connect(self.onSave)

Рекомендуется сразу же создать пустые методы для этих событий в классе Window и потом описать их. Иначе интерпретатор выдаст ошибку при попытке протестировать код.

5. Реализация функций загрузки и сохранения:

# When open button has been pressed

def onOpen(self):

    # Open file dialog and get path

    file = QFileDialog.getOpenFileName(self, 'Open image', '', 'Image files (*.jpg *.png *.bmp);;All files (*)')[0]

    # Create a pixmap from file

    img = QPixmap(file)

    # Check if it's an image

    if img.isNull() == False:

        # Set pixmap to label

        self.Image.setPixmap(img)

    elif file != "":

        # If it's not image and user didn't press 'Cancel' raise an error message

        msg = QMessageBox()

        msg.setIcon(QMessageBox.Critical)

        msg.setWindowTitle("Wrong file type")

        msg.setText("It's not an image. Please, open an image file.")

        msg.exec_()

# When save button has been pressed

def onSave(self):

    # Open file dialog and get path

    file = QFileDialog.getSaveFileName(self, 'Save image', '', '*.jpg;;*.png;;*.bmp;;Another type (*)')[0]

    # Get file type from file

    ftype = ''

    for i in range(len(file) - 1, -1, -1):

        if file[i] == '.':

        break

        else:

        ftype += file[i]

    # Reverse string and make it in uppercase for saving

    ftype = ftype[::-1].upper()

    # Finally save image

    try:

        self.Image.pixmap().save(file, ftype)

    except:

        # Or print an error message if something went wrong

        msg = QMessageBox()

        msg.setIcon(QMessageBox.Critical)

        msg.setWindowTitle("Error")

        msg.setText("Cannot save an image.")

        msg.exec_()

Таким образом, пользователь программы может открывать и сохранять изображения.

6. Добавление загрузки изображения по умолчанию после инициализации GUI, чтобы при открытии программы не отображался черный прямоугольник, пусть загружается логотип программы:

self.Image.setPixmap(QPixmap('logo.png'))

 

Рисунок 3. Скриншот программы с открытым изображением по умолчанию

 

7. Реализация загрузки модулей. Рекомендуется сначала написать шаблон для модуля, и только после этого реализовать метод добавления модулей, иначе придется действовать вслепую.

# Open file with list of modules

list = open('plugins/plugins.cfg', 'r')

# Add each listed module

for line in list:

    if line[0] != '#':

    # Remove \n from the end of the line

    # There will be no other such characters so we can use this simple method

    line = line.replace('\n', '')

    # Create an instance of module and give argument self as parent

    module = importlib.import_module('plugins.' + line).main(self)

    # Set unified height to all modules

    module.setMaximumHeight(48)

    # Put this module on the top

    self.layoutOnTop.addWidget(module)

При создании экземпляра модуля ядро импортирует его, создает его экземпляр и отправляет себя через аргумент «parent» конструктора. Это нужно для того, чтобы модули могли изменять интерфейс программы, например, добавить плавающие панели или движок тем.

8. Чтобы виджеты загруженных модулей не растягивались на всю ширину окна, необходимо добавить к панели растягивание (метод addStretch()) после загрузки модулей:

self.layoutOnTop.addStretch()

Скриншот запущенной программы с загруженными модулями представлен на рисунке 4:

 

Рисунок 4. Скриншот запущенной программы с загруженными модулями

 

1.3. Разработка модуля «Оттенки серого»

На данном этапе для примера создается модуль, представляющий собой подкласс QPushButton, который будет выполнять функции обесцвечивания изображения (фильтр «оттенки серого»). Данный фильтр уже присутствует в Qt, но для примера был создан свой алгоритм (также в поставку программы входит модуль фильтра “сепия”, описание его создания опустим).

Модуль должен представлять собой класс «main», а его конструктор должен иметь аргумент класса окна программы (QMainWindow). Класс main может быть любого типа.

Ниже приведен код модуля, который представляет собой кнопку:

# For creating class

from PyQt5.QtWidgets import QPushButton

# For converting

from PyQt5.QtGui import QPixmap, QColor

# Create our custom QPushButton widget class called main (necessary)

class main(QPushButton):

    # Initialize widget

    # Parent is application main window

    def __init__(self, parent):

       

        # Make our module super awesome

        super().__init__()

Далее производится работа с приведенным выше примером.

1. Изменение внешнего вида виджета:

# Set width of this widget (self)

self.setMinimumWidth(70)

# Set text on button

self.setText('Grayscale')

2. Подключение события по нажатию на кнопку. Чтобы передать объект parent в обработчик события, используется лямбда-функция.

# Make a connection to click event

self.clicked.connect(lambda: self.action(parent))

3. Метод обработчика события и, соответственно, алгоритма фильтра:

def action(self, parent):

       

    # Try to convert image to pixmap or return None if no image has been loaded

    try:

        image = parent.Image.pixmap().toImage()

    except:

        return None

       

    # Now make it all gray

    for i in range(image.width()):

        for j in range(image.height()):

        # Create a temporary variables

        # Color

        color = image.pixelColor(i, j).getRgb()

        # Alpha

        alpha = color[3]

        # Gray color will be arithmetic mean of all colors in pixel

        gray = int((color[0] + color[1] + color[2]) / 3)

        # Apply new color to current pixel

        image.setPixel(i, j, QColor(gray, gray, gray, alpha).rgba())

       

    # Show the new image

    parent.Image.setPixmap(QPixmap.fromImage(image))

По нажатию на кнопку изображение будет содержать только оттенки серого.

 

Рисунок 5. Изображения слева направо: оригинальное изображение, изображение с примененным фильтром «оттенки серого», изображение с примененным фильтром «сепия»

 

Заключение

В данной статье был показан конкретный пример разработки ПО с модульной структурой.

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

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

 

Список литературы:

  1. Исходный код графического редактора YAMIE. – [Электронный ресурс] – Режим доступа: URL: https://github.com/matafokka/YAMIE (дата обращения 15.01.2020)
  2. Статья «Модульное программирование» – [Электронный ресурс] – Режим доступа: URL: https://vslovar.org.ru/comp/599.html (дата обращения 10.02.2020)
  3. «Визуальный словарь» – [Электронный ресурс] – Режим доступа: URL: https://vslovar.org.ru/comp/597.html (дата обращения 10.02.2020)
  4. Find events from the Python Community around the world! – [Электронный ресурс] – Режим доступа: URL: https://www.python.org/about/ (дата обращения 10.02.2020).
  5. М. Саммерфилд. Программирование на Python 3 – СПб: Символ-Плюс. 2018. – 607 с.
Проголосовать за статью
Конференция завершена
Эта статья набрала 0 голосов
Дипломы участников
У данной статьи нет
дипломов

Оставить комментарий

Форма обратной связи о взаимодействии с сайтом
CAPTCHA
Этот вопрос задается для того, чтобы выяснить, являетесь ли Вы человеком или представляете из себя автоматическую спам-рассылку.