Литмир - Электронная Библиотека
A
A

  static void cb_next(Address, Address);

  static void cb_quit(Address, Address);

};

 

Программирование. Принципы и практика использования C++ Исправленное издание - _001.png
 Обратите внимание на то, что все члены, кроме конструкторов, являются закрытыми. В принципе этот класс и является программой. Все, что происходит, происходит с помощью обратных вызовов, поэтому никакого кода, кроме этого класса, не требуется. Мы упорядочили объявления, чтобы определение класса стало более удобочитаемым. Конструктор передает аргументы всем своим подобъектам и связывает их с окном.

Lines_window::Lines_window(Point xy,int w,int h,

            const string&title)

  :Window(xy,w,h,title),

  next_button(Point(x_max()–150,0),70,20,

  "Next point", cb_next),

  quit_button(Point(x_max()–70,0),70,20,"Quit",cb_quit),

  next_x(Point(x_max()–310,0),50,20,"next x:"),

  next_y(Point(x_max()–210,0),50,20,"next y:"),

  xy_out(Point(100,0),100,20,"current (x,y):")

  color_menu(Point(x_max()–70,30),70,20,Menu::vertical,"color"),

  menu_button(Point(x_max()–80,30),80,20,

  "color menu",cb_menu),

  {

    attach(next_button);

    attach(quit_button);

    attach(next_x);

    attach(next_y);

    attach(xy_out);

    xy_out.put("нет точек");

    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);

    color_menu.hide();

    attach(menu_button);

    attach(lines);

}

Обратите внимание на то, что инициализация выполняется в порядке определения данных-членов. Это правильный порядок инициализации. Фактически инициализация членов всегда происходит в порядке их объявления. Некоторые компиляторы выдают предупреждения, если конструктор базового класса или члена нарушает этот порядок. 

16.8. Отладка программы графического пользовательского интерфейса

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

main()
.

int main()

{

  Lines_window (Point(100,100),600,400,"lines");

  return gui_main();

}

 

Программирование. Принципы и практика использования C++ Исправленное издание - _001.png
 Вы видите ошибку? Независимо от того, видите ли вы ее или нет, эту программу следует испытать; она компилируется и выполняется, но вместо линий на экране в лучшем случае появляется какое-то мерцание. Как найти ошибку в такой программе? Для этого можно сделать следующее.

• Тщательно исследовать части программы (классы, функции, библиотеки).

• Упростить все добавления, понемногу увеличивая объем программы, начиная с простейшей версии и тщательно отслеживая строку за строкой.

• Проверить все установки редактора связей.

• Сравнить ее с уже работающей программой.

• Объяснить код другу.

 

Программирование. Принципы и практика использования C++ Исправленное издание - _003.png
 Среди всех этих предложений самым трудным является отслеживание выполнения кода. Если вы умеете работать с отладчиком программ, у вас есть шанс, но простая вставка операторов вывода в данном случае бесполезна — проблема заключается в том, что никакой вывод на экране не появится. Даже отладчики иногда испытывают проблемы, поскольку в компьютере несколько действий выполняется одновременно (многопоточность), так как ваша программа — не единственная программа, пытающаяся взаимодействовать с экраном. Главное — упростить код и систематически его исследовать.

Итак, в чем же проблема? Вот правильная версия (см. раздел 16.5).

int main()

{

  Lines_window win(Point(100,100),600,400,"lines");

  return gui_main();

}

Мы забыли указать имя

win
объекта класса
Lines_window
. Поскольку на самом деле мы не используем это имя, это кажется разумным, но компилятор решит, что, поскольку вы не используете окно, его можно сразу удалить. Ой! Это окно существовало всего несколько миллисекунд. Ничего удивительно, что мы его не заметили.

 

Программирование. Принципы и практика использования C++ Исправленное издание - _003.png
 Другая распространенная проблема заключается в том, что окно располагается точно поверх другого окна. Это выглядит так, будто на экране открыто только одно окно. А куда делось другое? Мы можем долго искать несуществующие ошибки в своей программе. Та же самая проблема может возникнуть, если вы размещаете одну фигуру поверх другой.

 

Программирование. Принципы и практика использования C++ Исправленное издание - _003.png
 И в заключение (чтобы еще больше огорчить читателей) отметим, что при работе с библиотеками графического пользовательского интерфейса исключения не всегда срабатывают так, как мы от них ожидаем. Поскольку наша программа управляется библиотекой графического пользовательского интерфейса, сгенерированное исключение может никогда не попасть к своему обработчику — библиотека или операционная система может “съесть” его (т.е. использовать механизмы обработки ошибок, отличающиеся от исключения языка С++).

 

Программирование. Принципы и практика использования C++ Исправленное издание - _001.png
 К типичным проблемам, выявляемым при отладке, относится и отсутствие изображений объектов
Shape
и
Widget
из-за отсутствия связи с окном или неправильного поведения объекта. Однако их описание выходит за рамки нашей книги. Посмотрите, как программист может создать и связать кнопку с меню, породив проблемы.

218
{"b":"847443","o":1}