- Любовные романы
- Фантастика и фэнтези
- Ненаучная фантастика
- Ироническое фэнтези
- Научная Фантастика
- Фэнтези
- Ужасы и Мистика
- Боевая фантастика
- Альтернативная история
- Космическая фантастика
- Попаданцы
- Юмористическая фантастика
- Героическая фантастика
- Детективная фантастика
- Социально-психологическая
- Боевое фэнтези
- Русское фэнтези
- Киберпанк
- Романтическая фантастика
- Городская фантастика
- Технофэнтези
- Мистика
- Разная фантастика
- Иностранное фэнтези
- Историческое фэнтези
- LitRPG
- Эпическая фантастика
- Зарубежная фантастика
- Городское фентези
- Космоопера
- Разное фэнтези
- Книги магов
- Любовное фэнтези
- Постапокалипсис
- Бизнес
- Историческая фантастика
- Социально-философская фантастика
- Сказочная фантастика
- Стимпанк
- Романтическое фэнтези
- Ироническая фантастика
- Детективы и Триллеры
- Проза
- Юмор
- Феерия
- Новелла
- Русская классическая проза
- Современная проза
- Повести
- Контркультура
- Русская современная проза
- Историческая проза
- Проза
- Классическая проза
- Советская классическая проза
- О войне
- Зарубежная современная проза
- Рассказы
- Зарубежная классика
- Очерки
- Антисоветская литература
- Магический реализм
- Разное
- Сентиментальная проза
- Афоризмы
- Эссе
- Эпистолярная проза
- Семейный роман/Семейная сага
- Поэзия, Драматургия
- Приключения
- Детская литература
- Загадки
- Книга-игра
- Детская проза
- Детские приключения
- Сказка
- Прочая детская литература
- Детская фантастика
- Детские стихи
- Детская образовательная литература
- Детские остросюжетные
- Учебная литература
- Зарубежные детские книги
- Детский фольклор
- Буквари
- Книги для подростков
- Школьные учебники
- Внеклассное чтение
- Книги для дошкольников
- Детская познавательная и развивающая литература
- Детские детективы
- Домоводство, Дом и семья
- Юмор
- Документальные книги
- Бизнес
- Работа с клиентами
- Тайм-менеджмент
- Кадровый менеджмент
- Экономика
- Менеджмент и кадры
- Управление, подбор персонала
- О бизнесе популярно
- Интернет-бизнес
- Личные финансы
- Делопроизводство, офис
- Маркетинг, PR, реклама
- Поиск работы
- Бизнес
- Банковское дело
- Малый бизнес
- Ценные бумаги и инвестиции
- Краткое содержание
- Бухучет и аудит
- Ораторское искусство / риторика
- Корпоративная культура, бизнес
- Финансы
- Государственное и муниципальное управление
- Менеджмент
- Зарубежная деловая литература
- Продажи
- Переговоры
- Личная эффективность
- Торговля
- Научные и научно-популярные книги
- Биофизика
- География
- Экология
- Биохимия
- Рефераты
- Культурология
- Техническая литература
- История
- Психология
- Медицина
- Прочая научная литература
- Юриспруденция
- Биология
- Политика
- Литературоведение
- Религиоведение
- Научпоп
- Психология, личное
- Математика
- Психотерапия
- Социология
- Воспитание детей, педагогика
- Языкознание
- Беременность, ожидание детей
- Транспорт, военная техника
- Детская психология
- Науки: разное
- Педагогика
- Зарубежная психология
- Иностранные языки
- Филология
- Радиотехника
- Деловая литература
- Физика
- Альтернативная медицина
- Химия
- Государство и право
- Обществознание
- Образовательная литература
- Учебники
- Зоология
- Архитектура
- Науки о космосе
- Ботаника
- Астрология
- Ветеринария
- История Европы
- География
- Зарубежная публицистика
- О животных
- Шпаргалки
- Разная литература
- Зарубежная литература о культуре и искусстве
- Пословицы, поговорки
- Боевые искусства
- Прочее
- Периодические издания
- Фанфик
- Военное
- Цитаты из афоризмов
- Гиды, путеводители
- Литература 19 века
- Зарубежная образовательная литература
- Военная история
- Кино
- Современная литература
- Военная техника, оружие
- Культура и искусство
- Музыка, музыканты
- Газеты и журналы
- Современная зарубежная литература
- Визуальные искусства
- Отраслевые издания
- Шахматы
- Недвижимость
- Великолепные истории
- Музыка, танцы
- Авто и ПДД
- Изобразительное искусство, фотография
- Истории из жизни
- Готические новеллы
- Начинающие авторы
- Спецслужбы
- Подростковая литература
- Зарубежная прикладная литература
- Религия и духовность
- Старинная литература
- Справочная литература
- Компьютеры и Интернет
- Блог
Программирование. Принципы и практика использования C++ Исправленное издание - Бьёрн Страуструп
Шрифт:
Интервал:
Закладка:
ss << '(' << x << ',' << y << ')';
xy_out.put(ss.str());
redraw();
}
Все это совершенно очевидно. Функция get_int() позволяет получить целочисленные координаты из объектов класса In_box; поток ostringstream форматирует строки для вывода в объект класса Out_box; функция-член str() позволяет вставить строку в поток ostringstream. Финальная функция, redraw(), необходима для представления результатов пользователю; старое изображение остается на экране, пока не будет вызвана функция redraw() из класса Window.
А что нового в этой программе? Посмотрим на ее функцию main().
#include "GUI.h"
int main()
try {
Lines_window win(Point(100,100),600,400,"lines");
return gui_main();
}
catch(exception& e) {
cerr << "Исключение: " << e.what() << 'n';
return 1;
}
catch (...) {
cerr << "Какое-то исключениеn";
return 2;
}
Так ведь здесь, по существу, ничего нет! Тело функции main() содержит лишь определение нашего окна win и вызов функции gui_main(). Ни других функций, ни операторов if или switch, ни цикла — ничего из того, чтобы изучали в главах 6–7, — только определение переменной и вызов функции gui_main(), которая сама вызывает функцию run() из библиотеки FLTK. Изучая программу далее, увидим, что функция run() — это просто бесконечный цикл.
while(wait());
За исключением некоторых деталей реализации, описание которых вынесено в приложение Д, мы просмотрели весь код, запускающий программу рисования линий. Мы увидели всю логику этой программы. Что же произошло?
16.6. Инверсия управления
А произошло вот что: мы передали поток управления от самой программы элементам управления окном: теперь программа возобновляет свою работу каждый раз, когда активизируется какой-нибудь из этих элементов. Например, щелкните на кнопке, и программа начнет работать. После возврата обратного вызова программа “отключается”, ожидая, пока пользователь сделает что-нибудь еще. По существу, функция wait() просит систему опросить элементы управления окном и активизировать соответствующие обратные вызовы. Теоретически функция wait() могла бы сообщать, какой элемент управления требует внимания, и предоставить самому программисту вызывать соответствующую функцию. Однако в библиотеке FLTK и в большинстве других систем графического пользовательского интерфейса функция wait() активизирует соответствующий обратный вызов, освобождая программиста от необходимости писать код для выбора этой функции.
Обычная программа организована следующим образом:
Программа графического пользовательского интерфейса организована иначе.
Одна из сложностей такой инверсии управления проявляется в том, что порядок выполнения программы теперь полностью определяется действиями пользователя. Это усложняет как организацию, так и отладку программы. Трудно себе представить, что сделает пользователь, но еще труднее представить себе возможные результаты случайной последовательности обратных вызовов. Это превращает систематическое тестирование в ночной кошмар (подробнее об этом — в главе 26). Методы решения этой проблемы выходят за рамки рассмотрения нашей книги, но мы просим читателей быть особенно осторожными, работая с кодом, управляемым пользователями с помощью обратных вызовов. Кроме очевидных проблем с потоком управления, существуют проблемы, связанные с видимостью и отслеживанием связей между элементами управления окном и данными. Для того чтобы минимизировать трудности, очень важно не усложнять часть программы, отвечающую за графический пользовательский интерфейс, и создавать ее постепенно, тестируя каждую часть. Работая с программой графического пользовательского интерфейса, почти всегда необходимо рисовать небольшие диаграммы объектов и взаимодействия между ними.
Как взаимодействуют части программы, активизированные разными обратными вызовами? Проще всего, чтобы функции оперировали данными, хранящимися в окне, как показано в примере из раздела 16.5. В нем функция next() класса Lines_window активизировалась щелчком на кнопке Next point, считывала данные из объектов класса In_box (next_x и next_y), а затем обновляла переменную-член lines и объект класса Out_box (xy_out). Очевидно, что функция, активизированная обратным вызовом, может делать все, что угодно: открывать файлы, связываться с сетью веб и т.д. Однако пока мы рассмотрим простой случай, когда данные хранятся в окне.
16.7. Добавление меню
Исследуем вопросы управления и взаимодействия, поднятые в разделе “Инверсия управления”, на примере создания меню для программы, рисующей линии. Для начала опишем меню, позволяющее пользователю выбирать цвет всех линий в переменной lines. Добавим меню color_menu и обратные вызовы.
struct Lines_window:Window {
Lines_window(Point xy,int w,int h,const string& title);
Open_polyline lines;
Menu color_menu;
static void cb_red(Address,Address); // обратный вызов
// для красной кнопки
static void cb_blue(Address,Address); // обратный вызов
// для синей кнопки
static void cb_black(Address,Address); // обратный вызов
// для черной кнопки
// действия:
void red_pressed() { change(Color::red); }
void blue_pressed() { change(Color::blue); }
void black_pressed() { change(Color::black); }
void change(Color c) { lines.set_color(c); }
// ...как и прежде...
};
Создание всех таких практически идентичных функций обратного вызова и функций “действия” — довольно утомительное занятие. Однако оно не вызывает никаких затруднений, а описание более простых средств выходит за рамки нашей книги. После щелчка на кнопке меню цвет линий изменяется на требуемый.
Определив член color_menu, мы должны его инициализировать.
Lines_window::Lines_window(Point xy,int w,int h,
const string&title):Window(xy,w,h,title),
// ...как и прежде...
color_menu(Point(x_max()–70,40),70,20,Menu::vertical,"color")
{
// ...как и прежде...
color_menu.attach(new Button(Point(0,0),0,0,"red",cb_red));
color_menu.attach(new Button(Point(0,0),0,0,"blue",cb_blue));
color_menu.attach(new Button(Point(0,0),0,0,"black",cb_black));
attach(color_menu);
}
Кнопки динамически связываются с меню (с помощью функции attach()) и при необходимости могут быть удалены и/или изменены. Функция Menu::attach() настраивает размер и место кнопки, а также связывает его с окном. Это все. Теперь мы увидим на экране следующее.
Экспериментируя с этой программой, мы решили, что нам необходимо выпадающее меню; т.е. мы не хотим фиксировать конкретное место на экране, в котором оно будет появляться. Итак, мы добавили кнопку Color menu. Когда пользователь щелкнет на ней, всплывет меню цвета, а после того как выбора меню снова исчезнет, и на экране отобразится кнопка.
Посмотрим сначала на окно, в которое добавлено несколько линий.
Мы видим новую

