Перейти к основному содержимому

Архитектура десктопных приложений

Разработчику Архитектору Инженеру

Как устроены десктопные приложения

Десктопное приложение - окно, события и mainloop

Прежде чем писать код на Tkinter, Qt или Electron, стоит увидеть общую схему — окно, очередь событий, UI-поток и граница с ОС через драйверы. Тогда "зависание кнопки" и "почему нужен mainloop" становятся предсказуемыми.

Практика по языкам — в разделе десктоп; особенности потоков и памяти — Особенности разработки десктопных приложений.


Что такое десктопное приложение?

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

Основой любого такого приложения является графический интерфейс пользователя (GUI) — способ взаимодействия человека с программой через динамически выводимые на экран объекты. Пользователь выбирает элемент и действует с ним напрямую (тачскрин, стилус) или через курсор, управляемый мышью, клавиатурой или другим устройством. Элементы, с которыми можно взаимодействовать, называют виджетами (widgets) или контролами (controls).


Графический интерфейс — от пульта к WIMP

До появления GUI оператор работал с ЭВМ через командную строку или специализированный пульт с физическими переключателями. Такой пульт подходил для одной узкой задачи, но при усложнении системы превращался в громоздкую панель. Графический интерфейс стал практичным, когда появились дисплеи достаточного разрешения и указательное устройство.

В 1960-х Даг Энгельбарт (Stanford Research Institute) свёл разрозненные идеи графического взаимодействия в единую систему и в 1968 году продемонстрировал мышь на конференции, которую позже назвали The Mother of All Demos. Концепцию развили в Xerox PARC — там оформилась модель WIMPWindows, Icons, Menus, Pointer (окна, значки, меню, указатель). Коммерчески WIMP закрепился в продуктах Apple (1984) и позже в AmigaOS (1985) с многозадачностью.

На настольных компьютерах WIMP до сих пор задаёт "язык" большинства программ — окно с заголовком, меню сверху, панель инструментов, область документа и строка состояния — всё это наследники той модели.

Вид GUIХарактеристикаПримеры
ПростойСтандартные формы и контролы, которые даёт сама подсистема GUI ОСWinForms, классические диалоги Windows
Истинно графический (2D)Нестандартные элементы, собственные метафоры, кастомная отрисовкаWPF, Qt с QML, Electron с CSS
ТрёхмерныйОбъёмная сцена как часть интерфейсаигры, CAD, часть Fluent Design в WinUI

Хороший GUI стремится к предсказуемости: пользователь интуитивно понимает, что произойдёт после действия. В HCI это называют принципом DWIM (Do What I Mean — "делай то, что я имею в виду"): кнопка "Сохранить" сохраняет, закрытие окна с несохранёнными данными спрашивает подтверждение.

GUI и стек Windows

Классические контролы WinForms — обёртка над Win32 и GDI+. WPF и WinUI рисуют через DirectX и описывают UI в XAML. Сравнение стеков — в 116.md; практикум по XAML — 119.md и справочник XAML.


Драйверы и доступ к устройствам

Приложение редко общается с "железом" напрямую. Когда нужно прочитать данные с принтера, диска, USB-устройства или сетевой карты, код вызывает функции операционной системы, а ОС передаёт запрос драйверу — программному компоненту, который знает, как говорить с конкретным устройством или его контроллером. Драйвер возвращает результат ядру, ядро — вашему приложению.

По определению Microsoft:

  • драйвер пишет не только производитель устройства — для стандартного оборудования драйвер может поставлять сама Microsoft;
  • запрос часто проходит стек драйверов (filter drivers, function driver, bus driver), а не один модуль;
  • есть драйверы программного обеспечения — компоненты в режиме ядра без привязки к железу (доступ к защищённым структурам ОС).

Для обычного десктоп-разработчика важно понимать границу: UI и бизнес-логика живут в пользовательском режиме, а драйверы — в режиме ядра; ошибка в драйвере может нарушить стабильность всей системы. Подробнее о платформе Windows, стеках и среде разработки — в статье Разработка приложений для Windows (Microsoft Learn).

image-1.png

Здесь мы видим пример типичного десктопного приложения, в котором имеется полный набор. Давайте же разберём структуру.


Play ITЗагрузка интерактивного демо…


Архитектура окна и основные компоненты

Окно представляет собой фундаментальную единицу взаимодействия в десктопном приложении.

Это прямоугольная область на экране, ограниченная рамкой, которой управляет операционная система.

Каждое окно обладает:

  • собственным контекстом отрисовки,
  • координатной системой,
  • набором свойств, определяющих его поведение.

Типичное окно состоит из нескольких стандартных зон.


Заголовок

Верхняя часть называется заголовком (Title Bar). Заголовок содержит название приложения или текущего документа, а также кнопки управления окном. Эти кнопки позволяют свернуть окно в панель задач, развернуть его на весь экран или закрыть приложение. Заголовок также служит областью захвата для перемещения окна по экрану с помощью мыши.

image-2.png


Меню

Под заголовком часто располагается меню (Menu). Это горизонтальная панель со списком категорий действий, таких как Файл, Правка, Вид. При нажатии на пункт меню открывается выпадающий список с конкретными командами. Меню обеспечивает доступ ко всем основным функциям программы в структурированном виде.

image-3.png


Панель инструментов

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

image-4.png


Область контента

Центральная часть окна называется областью контента (Content Area). Здесь отображается основная информация — текст документа, изображение, таблица данных или форма ввода. Область контента занимает все свободное пространство между верхними панелями и нижними элементами интерфейса.

image-5.png


Строка состояния

В нижней части окна часто размещается строка состояния (Status Bar). Строка состояния отображает справочную информацию о текущем режиме работы, координатах курсора, прогрессе выполнения операции или сообщения об ошибках. Она носит информационный характер и редко содержит элементы управления.

image-6.png image-18.png


Полоса прокрутки

Если содержимое области контента не помещается в видимую часть окна, появляются полосы прокрутки (Scrollbars). Вертикальная полоса находится справа, горизонтальная — снизу. Полосы прокрутки позволяют перемещать видимую область относительно всего содержимого. Пользователь перетаскивает ползунок или нажимает на стрелки для навигации по документу.

image-7.png


Вкладки

Современные интерфейсы активно используют вкладки (Tabs). Вкладки позволяют группировать различные документы или настройки в одном окне. Переключение между вкладками меняет содержимое центральной области, не создавая новых окон. Это экономит место на экране и упорядочивает работу с множеством открытых файлов.

image-8.png


Элементы управления и ввод данных

Интерфейс приложения строится из набора стандартных элементов управления (Widgets или Controls). Каждый элемент имеет четкое назначение и реагирует на действия пользователя.


Label

Label (Метка) — простейший элемент для отображения статического текста. Метки используются для подписей полей ввода, заголовков разделов или пояснений. Текст в метке недоступен для редактирования пользователем.

image-9.png


TextBox

TextBox (Поле ввода) предназначено для ввода текста пользователем. Поле может быть однострочным (для имени, пароля) или многострочным (для заметок, кода). При вводе текста программа получает событие изменения содержимого и может реагировать на него мгновенно или по факту потери фокуса.

image-10.png


Button

Button (Кнопка) инициирует действие при нажатии. Кнопка имеет визуальное состояние — обычное, нажатое, наведенное курсором и неактивное. Нажатие кнопки отправляет команду в логику приложения для выполнения конкретной функции.

image-11.png


ComboBox

ComboBox (Выпадающий список) сочетает поле ввода и список вариантов. Пользователь может выбрать готовый вариант из списка или ввести свое значение, если это разрешено настройками. Этот элемент экономит место, скрывая список до момента взаимодействия.

image-12.png


ListBox

ListBox (Список) отображает перечень элементов для выбора. Список поддерживает выбор одного или нескольких пунктов.

image-13.png


DataGrid

DataGrid (Таблица) представляет данные в виде строк и столбцов. Таблицы позволяют сортировать данные, изменять размер колонок и редактировать ячейки напрямую.


Checkbox

Checkbox (Флажок) позволяет включить или выключить опцию. Состояние флажка бинарное: отмечено или не отмечено.

image-14.png


Progress bar

Progress bar (Индикатор прогресса) визуализирует длительность операции. Полоса заполняется пропорционально выполненной работе, давая пользователю понимание времени ожидания.

image-15.png


Поле поиска (Search Box) специализировано для фильтрации данных. При вводе символов приложение автоматически обновляет отображаемый список, оставляя только совпадающие элементы.

image-16.png


Справочники — как добавить элемент в код

Пошаговые рецепты "импорт → создать → разместить → обработчик" для каждого контрола: Tkinter, примеры Tkinter (Lab), JavaFX и Swing, примеры Swing (Lab), WinForms, примеры WinForms и WPF (Lab), WPF. Старт приложения — в "Первой программе": Tkinter, JavaFX, WPF, WinForms, Lab — простые окна на C#.


Диалоговые окна и всплывающие элементы

Диалоговое окно — это специальное окно, которое блокирует работу с основным интерфейсом до получения ответа от пользователя.

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

image-17.png

Всплывающие окна (Popups) включают подсказки (Tooltips), контекстные меню и уведомления.

Подсказка появляется при наведении курсора на элемент и кратко объясняет его функцию.

Контекстное меню вызывается правой кнопкой мыши и предлагает действия, релевантные текущему объекту под курсором.

Уведомления информируют о завершении фоновых задач без прерывания работы.


Отрисовка и рендеринг

Процесс отображения элементов на экране называется рендерингом. Операционная система предоставляет приложению поверхность для рисования.

Библиотеки интерфейса (такие как WinAPI, WPF, Qt, Electron) преобразуют код программы в последовательность графических примитивов:

  • линий;
  • прямоугольников;
  • текста;
  • изображений.

На Windows два распространённых пути отрисовки desktop UI:

СтекМеханизмКогда выбирают
WinForms, классический Win32GDI / GDI+ — рисование через контекст устройства и HWNDстандартные формы, нативный вид ОС
WPF, WinUIDirectX — аппаратное ускорение, векторная графикакастомный дизайн, анимация, HiDPI

Подробнее о DirectX и выборе платформы — Разработка приложений для Windows (Microsoft Learn).

Отрисовка происходит поэтапно:

  • Сначала рассчитывается макет (Layout): размеры и положение каждого элемента с учетом границ окна и свойств вложенности.
  • Затем формируется дерево визуальных объектов. Графический движок проходит по этому дереву и отправляет команды видеокарте или процессору для рисования пикселей.

При изменении размера окна или обновлении данных система помечает измененные области как требующие перерисовки (Invalidation). Основной цикл программы затем вызывает метод отрисовки только для этих областей, что оптимизирует производительность. Границы окна определяют clipping region — область, за пределы которой рисунок не выйдет.


События, обработка и основной цикл

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

Событие — это сигнал о действии — нажатие клавиши, движение мыши, клик, изменение размера окна, таймер.

Координаты мыши отслеживаются операционной системой постоянно. При движении курсора система генерирует событие перемещения с координатами X и Y относительно левого верхнего угла окна или экрана. Приложение получает эти координаты и определяет, над каким элементом управления находится курсор. Это позволяет менять вид кнопки при наведении или выделять элемент списка.

Регистрация клика мыши происходит при нажатии и отпускании кнопки манипулятора. Система проверяет, не переместился ли курсор слишком сильно между нажатием и отпусканием. Если условие выполнено, генерируется событие Click.

Обработчик события (Event Handler) — это функция в коде, которая выполняется в ответ на это действие. Разработчик связывает кнопку с функцией, и при клике запускается нужный алгоритм.

Ввод текста генерирует серию событий:

  • нажатие клавиши (KeyDown),
  • появление символа (KeyPress),
  • отпускание клавиши (KeyUp).

Поле ввода перехватывает эти события, обновляет внутреннее хранилище текста и инициирует событие изменения содержимого (TextChanged), уведомляя остальные части программы о новых данных.

Сердцем приложения является основной цикл (Main Loop) или цикл сообщений (Message Loop). Этот бесконечный цикл работает пока приложение запущено. На каждой итерации цикл запрашивает у операционной системы новые сообщения из очереди событий. Если очередь пуста, цикл переходит в режим ожидания, экономя ресурсы процессора. При получении сообщения цикл определяет тип события и вызывает соответствующий обработчик.

Без основного цикла приложение не сможет реагировать на действия пользователя. Окно зависнет, перестанет перерисовываться и операционная система пометит его как Не отвечает. Завершение работы программы означает выход из этого цикла.

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

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

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


Пример десктопного приложения на Python

Настоятельно рекомендую ознакомиться со главой, посвящённой созданию десктопных приложений на Python - 5.02. Графика и игры.

Если же вы не знаете язык Python, вам лучше предварительно ознакомиться с этим языком.

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

Скопируйте этот код в файл с расширением .py, например demo_app.py, и запустите его через терминал или командную строку.

Код ITЗагрузка примера кода…


Инициализация и окно

Класс DesktopAppDemo принимает объект root, который является главным окном приложения. Метод root.geometry задает начальные размеры в пикселях. Метод root.title устанавливает текст в заголовке окна. Все дальнейшие элементы создаются внутри этого окна или внутри фреймов-контейнеров.


Меню и панель инструментов

Объект tk.Menu создает горизонтальное меню в верхней части окна. Метод add_cascade связывает выпадающие списки с пунктами верхнего уровня. Пункты меню привязываются к функциям через параметр command. Панель инструментов реализована через tk.Frame, прикрепленный к верхней стороне окна (side=tk.TOP). Кнопки внутри нее упакованы слева направо. Это дублирует функции меню для быстрого доступа.


Вкладки и контейнеры

Библиотека ttk предоставляет более современные виджеты. ttk.Notebook создает область с вкладками. Каждая вкладка — это отдельный Frame, который добавляется в книгу через метод add. Внутри каждой вкладки размещаются свои уникальные элементы управления. Такая структура позволяет компактно разместить много функционала в одном окне.


Элементы ввода

Поле Entry используется для однострочного ввода. Обработчики событий <FocusIn> и <FocusOut> реализуют поведение подсказки (placeholder): текст подсказки исчезает при клике и возвращается, если поле осталось пустым. ttk.Combobox предоставляет выпадающий список. Атрибут state="readonly" запрещает ввод произвольного текста, оставляя только выбор из списка. Событие &lt;&lt;ComboboxSelected&gt;&gt; срабатывает при изменении выбора. Checkbutton связан с переменной BooleanVar, что позволяет легко проверять состояние флажка в коде. scrolledtext.ScrolledText представляет собой многострочное текстовое поле с автоматически добавленной полосой прокрутки.


Списки и фильтрация

Listbox отображает перечень строк. Вертикальная полоса прокрутки Scrollbar связывается со списком через конфигурацию yscrollcommand и command, обеспечивая синхронную прокрутку. Событие <KeyRelease> на поле поиска запускает функцию filter_list при каждом отпускании клавиши. Функция очищает список и заполняет его заново, оставляя только элементы, содержащие введенную подстроку. Это демонстрирует реактивность интерфейса на ввод данных.


Индикаторы прогресса

ttk.Progressbar визуализирует длительность задачи. В режиме determinate значение устанавливается явно. Функция run_progress использует метод root.after, чтобы запланировать следующий шаг обновления через 50 миллисекунд. Это имитирует длительную операцию без блокировки основного цикла программы. Если использовать обычный цикл while, интерфейс зависнет до завершения работы.


Контекстное меню и события мыши

Метод bind("<Button-3>", ...) регистрирует нажатие правой кнопки мыши на главном окне. При этом вызывается функция show_context_menu, которая отображает всплывающее меню tk.Menu в координатах курсора (event.x_root, event.y_root).


Основной цикл

В конце скрипта создается экземпляр главного окна tk.Tk() и запускается метод root.mainloop(). Эта команда передает управление операционной системе. Система начинает непрерывно опрашивать очередь событий — движения мыши, нажатия клавиш, таймеры перерисовки. Пока этот цикл работает, окно остается открытым и реагирует на действия. Закрытие окна пользователем прерывает цикл, и программа завершает работу.


Частые ошибки

СимптомПричина
UI "зависает"Долгая работа в UI-потоке
Окно не закрываетсяНе обработано событие закрытия
Двойной mainloopВторой вызов mainloop() блокирует логику

Что попробовать

  1. Симулятор окна на этой странице (DesktopWindowPlay).
  2. Особенности разработки десктопных приложений — вынести тяжёлую задачу из UI-потока.
  3. Electron, WinForms (Lab — примеры), Tkinter (примеры), Java Swing (примеры) или React + ElectronПервая программа Electron с React — выбрать стек.

В подборках

Статья входит в тематические подборки и блок "С чего начать?" на главной. Соседние шаги того же маршрута:

Цифровая грамотностьОсновы информационной безопасности — о разделе, Интернет-культура — о разделе, Государственное регулирование интернета, Основы бизнеса для IT-специалиста, Государство и цифровая экономика, Потребительская грамотность в цифровой среде.

Офисная грамотностьУстройство и надёжность паролей, Настройка Windows, Цифровые формы и анкеты, Электронная почта, Текст — о разделе, Документация.

Архитектура и проектирование ПОАрхитектура выполнения — о разделе, Проектирование и архитектура — о разделе, Основы интеграционного взаимодействия — о разделе, Паттерны проектирования — о разделе, Аутентификация и авторизация, Проектирование — о разделе.