Программирование. Принципы и практика использования C++ Исправленное издание, стр. 181

rect00.set_color(Color::invisible);

rect11.set_color(Color::invisible);

rect12.set_color(Color::invisible);

rect21.set_color(Color::invisible);

rect22.set_color(Color::invisible);

Это приводит к следующему результату:

Программирование. Принципы и практика использования C++ Исправленное издание - _138.png

Обратите внимание на то, что цвет заполнения и цвет линии заданы параметром

invisible
, поэтому прямоугольник
rect22
на экране больше не виден.

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

draw_lines()
класса
Rectangle
становится немного запутанной.

void Rectangle::draw_lines() const

{

  if (fill_color().visibility()) { // заполнение

    fl_color(fill_color().as_int());

    fl_rectf(point(0).x,point(0).y,w,h);

  }

  if (color().visibility()) { // линии поверх заполнения

    fl_color(color().as_int());

    fl_rect(point(0).x,point(0).y,w,h);

  }

}

Как видим, библиотека FLTK содержит функции для рисования как заполненных прямоугольников (

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

13.10. Управление неименованными объектами

До сих пор мы именовали все наши графические объекты. Когда же объектов много, то присваивать всем им имена становится нецелесообразно. В качестве примера нарисуем простую цветную диаграмму, состоящую из 256 цветов, предусмотренных в палитре библиотеки, иначе говоря, раскрасим 256 квадратов и нарисуем их в матрице 16×16.

Вот что у нас получится.

Программирование. Принципы и практика использования C++ Исправленное издание - _139.png

Называть все эти 256 квадратов было бы не только утомительно, но и глупо. Очевидно, что “имя” левого верхнего квадрата в матрице определяется его местоположением в точке (0,0), а все остальные квадраты можно точно так же идентифицировать с помощью пар координат (i, j). Итак, нам необходим эквивалент матрицы объектов. Сначала мы подумали о векторе

vector<Rectangle>
, но оказалось, что он недостаточно гибок. Например, было бы неплохо иметь коллекцию неименованных объектов (элементов), не все из которых имеют одинаковые типы. Проблему гибкости мы обсудим в разделе 14.3, а здесь продемонстрируем наше решение: векторный тип, хранящий именованные и неименованные объекты.

template<class T> class Vector_ref {

public:

  // ...

  void push_back(T&);   // добавляет именованный объект

  void push_back(T*);   // добавляет неименованный объект

  T& operator[](int i); // индексация: доступ для чтения и записи

  const T& operator[](int i) const;

  int size() const;

};

Наше определение очень похоже на определение типа

vector
из стандартной библиотеки.

Vector_ref<Rectangle> rect;

Rectangle x(Point(100,200),Point(200,300));

// добавляем именованные объекты

rect.push_back(x);

// добавляем неименованные объекты

rect.push_back(new Rectangle(Point(50,60),Point(80,90)));

// используем объект rect

for (int i=0; i<rect.size(); ++i) rect[i].move(10,10);

 

Программирование. Принципы и практика использования C++ Исправленное издание - _001.png
 Оператор new описан в главе 17, а реализация класса
Vector_ref
— в приложении Д. Пока достаточно знать, что мы можем использовать его для хранения неименованных объектов. За оператором new следует имя типа (в данном случае
Rectangle
) и, необязательно, список инициализации (в данном случае
(Point(50,60),Point(80,90))
).

Опытные программисты заметят, что в данном примере мы не допускаем утечки памяти. С помощью классов

Rectangle
и
Vector_ref
мы можем экспериментировать с цветами. Например, можем нарисовать простую диаграмму, состоящую из 256 цветов.

Vector_ref<Rectangle> vr;

for (int i = 0; i<16; ++i)

  for (int j = 0; j<16; ++j) {

    vr.push_back(new Rectangle(Point(i*20,j*20),20,20));

    vr[vr.size()–1].set_fill_color(Color(i*16+j));

    win20.attach(vr[vr.size()–1]);

}

Мы создали объект класса

Vector_ref
, состоящий из 256 объектов класса
Rectangle
, организованный в объекте класса
Window
в виде матрицы 16×16. Мы приписали объектам класса
Rectangle
цвета 0, 1, 2, 3, 4 и т.д. После создания каждого из объектов этого типа они выводятся на экран.

Программирование. Принципы и практика использования C++ Исправленное издание - _140.png

13.11. Класс Text

Очевидно, что нам необходимо выводить на экран текст. Например, мы могли бы пометить “странный” объект класса

Closed_polyline
из раздела 13.8.

Text t(Point(200,200),"A closed polyline that isn't a polygon");