• Использовать интерфейс веб-браузера. В этом случае потребуются язык разметки (markup language), такой как HTML, а также язык сценариев (scripting language). Эта тема выходит за рамки рассмотрения нашей книги, но для приложений с удаленным доступом именно такой выбор часто оказывается самым удачным. В этом случае взаимодействие пользователя с программой также носит текстовый характер (на основе потоков символов). Браузер — это средство графического пользовательского интерфейса, которое переводит текст в графические элементы, транслирует щелчки мышью и другие действия пользователя в текстовые данные и отправляет их обратно программе.
Многие люди считают использование графического пользовательского интерфейса сущностью современного программирования, а взаимодействие с объектами на экране — его основной целью. Мы с этим не согласны: графический пользовательский интерфейс — это разновидность ввода-вывода, а отделение основной логики приложения от системы ввода-вывода является одним из основных принципов разработки программного обеспечения. При любой возможности мы предпочитаем провести четкую границу между основной логикой программы и той ее частью, которая осуществляет ввод и вывод. Такое отделение позволяет изменять способ взаимодействия с пользователем, переносить программу в другие операционные системы и, что еще боле важно, размышлять о логике программы и способах ее взаимодействия с пользователем независимо друг от друга.
Тем не менее графический пользовательский интерфейс важен и интересен в разных аспектах. В данной главе исследуются как способы интегрирования графических элементов в наши приложения, так и способы защиты основных принципов создания интерфейса от влияния субъективных вкусов.
16.2. Кнопка Next
Зачем мы предусмотрели кнопку Next, которая использовалась для управления графическими примерами в главах 12–15? В этих примерах фигуры рисовались после нажатия клавиши. Очевидно, что это простая форма программирования графического пользовательского интерфейса. Фактически она настолько проста, что некоторые люди могут сказать, что это ненастоящий графический пользовательский интерфейс. Однако посмотрим, как это было сделано, поскольку это приведет нас прямо к тому виду программирования, которое все признали как программирование графического пользовательского интерфейса.
Наш код в главах 12–15 был устроен примерно так:
// создаем объекты и/или манипулируем ими,
// изображаем их в объекте win класса Window
win.wait_for_button();
// создаем объекты и/или манипулируем ими,
// изображаем их в объекте win класса Window
win.wait_for_button();
// создаем объекты и/или манипулируем ими,
// изображаем их в объекте win класса Window
win.wait_for_button();
Каждый раз, достигая вызова функции
wait_for_button()
, мы могли видеть наши объекты на экране, пока не щелкали на кнопке, чтобы получить результаты работы другой части программы. С точки зрения программной логики этот код ничем не отличается от программы, записывающей строки текста на экране (в окне консоли), останавливающейся и ожидающей ввода данных с клавиатуры. Рассмотрим пример.
// определяем переменные и/или вычисляем значения, вырабатываем
// результаты
cin >> var; // ожидаем ввода
// определяем переменные и/или вычисляем значения, вырабатываем
// результаты
cin >> var; // ожидаем ввода
// определяем переменные и/или вычисляем значения, вырабатываем
// результаты
cin >> var; // ожидаем ввода
С точки зрения реализации эти два вида программы совершенно отличаются друг от друга. Когда программа выполняет инструкцию
cin>>var
, она останавливается и ждет, пока система не вернет символы, которые ввел пользователь. Однако система графического пользовательского интерфейса, управляющая экраном и отслеживающая вашу работу с мышью, следует другой модели: она определяет, где находится курсор мыши и что пользователь с нею делает (щелкает и т.д.). Если ваша программа ожидает каких-то действий, то она должна делать следующее.
• Указать, за чем должна следить система графического пользовательского интерфейса (например, “Кто-то щелкнул на кнопке Next”).
• Указать, что делать, когда произошло ожидаемое событие.
• Ожидать, пока графический пользовательский интерфейс определит требуемое действие.
Новый интересный аспект заключается в том, что система графического пользовательского интерфейса не просто возвращает управление вашей программе, она разрабатывается так, чтобы по-разному реагировать на разные действия пользователя, такие как щелчок мышью на одной из многих кнопок, изменение размера окна, перерисовка окна после закрытия вложенного окна и открытие выпадающих меню.
Мы просто хотим сказать диспетчеру: “Пожалуйста, проснись, когда кто-то щелкнет на кнопке”, иначе говоря, “Пожалуйста, продолжай выполнять мою программу, когда кто-то щелкнет на кнопке в то время, когда курсор будет в прямоугольной области, представляющей собой изображение моей кнопки”. Это простейшее действие, которое можно себе представить. Однако эта операция не предусмотрена системой — ее необходимо написать самому. Как это сделать — первый вопрос, который мы рассмотрим, приступая к изучению программирования графического пользовательского интерфейса.
16.3. Простое окно
В принципе система (т.е. комбинация библиотеки графического пользовательского интерфейса и операционной системы) непрерывно отслеживает положение курсора мыши и состояние ее кнопок. Программа может проявить интерес к определенной области экрана и попросить систему вызвать функцию, когда произойдет что-нибудь интересное. В частности, мы можем попросить систему вызвать одну из наших функций обратного вызова (callback functions), когда пользователь щелкнет на кнопке. Для этого необходимо сделать следующее.
• Определить кнопку.
• Отобразить ее на экране.
• Определить функцию, которую должен вызвать графический пользовательский интерфейс.
• Сообщить графическому пользовательскому интерфейсу о данной кнопке и функции.
• Подождать, когда графический пользовательский интерфейс вызовет нашу функцию.
Давайте сделаем это. Кнопка — это часть объекта класса
Window
, поэтому (в файле
Simple_window.h
) мы определим класс
Simple_window
, содержащий член
next_button
.