Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Объектно-ориентированное программирование.PDF
Скачиваний:
208
Добавлен:
01.05.2014
Размер:
3.64 Mб
Скачать

converted to PDF by BoJIoc

создания экземпляра данного класса;

вызова метода run для экземпляра класса приложения:

class simpleApp : public application

{

public:

simpleApp() : application("simple application") { }

};

void main()

{

simpleApp theApp; theApp.run();

};

В данном случае приложение просто отображает окно на экране и ждет, пока пользователь его закроет.

19.5. Класс application

Функции, предоставляемые классом application, показаны в табл. 19.1. Функция run() обычно является последней функцией, вызываемой в процедуре main. Функция

run() не имеет возвращаемого результата. Метод quit() служит для прекращения работы приложения.

Методы update() и clearAndUpdate() вызываются каждый раз, когда действия пользователя могут привести к обновлению экрана. Чаще всего это необходимо вследствие какого-либо события, например перемещения мыши или нажатия

Таблица 19.1. Методы класса application

converted to PDF by BoJIoc

клавиши на клавиатуре. Метод clearAndUpdate() сначала очищает экран перед обновлением. Чтобы выполнить обновление, вызывается метод paint(). Обычно пользователь не обращается к методу paint() непосредственно.

Метод paint() перерисовывает изображение на экране дисплея. Обычно в классах приложения он переопределяется, чтобы обеспечить требуемое поведение. Он не должен непосредственно вызываться пользователем данный метод запускается как реакция на вызов методов update() или clearAndUpdate().

Если нажата кнопка мыши, вызывается метод mouseButtonDown(). Два его целочисленных

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

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

Когда пользователь нажимает клавишу на клавиатуре, вызывается метод keyPressed(). В качестве аргумента он получает символ, эквивалентный нажатой клавише.

converted to PDF by BoJIoc

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

В классе application доступны несколько элементарных процедур рисования и вывода на печать. Обычно вызовы графических функций выполняются во время обновления экрана. Если используется метод clearAndUpdate(), то любые действия, связанные с отображением графики, выполненные до вызова этой процедуры, будут потеряны. Таким образом, вызовы графических подпрограмм обычно производятся (прямо или косвенно) из метода paint(). Координаты для рисования даются в той же системе отсчета, что и для нажатия мыши. Иначе говоря, величина (0,0) представляет собой верхний левый угол окна, значения по оси OX увеличиваются вправо, а значения по оси OY — вниз. Последнее часто противоречит ожиданиям начинающих программистов.

19.5.1. Класс button

Разновидности кнопок создаются путем порождения подклассов из класса button и переопределения виртуального метода pressed. Как только кнопка присоединена к окну, этот метод вызывается автоматически при нажатии кнопки:

class quitButtonClass : public button

{

public:

quitButtonClass (window * win)

: button (win, "Quit", 5, 5, 20, 50)

{}

protected:

pressed (window * win)

{

...

}

};

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

описывается как часть состояния нового класса приложения и инициализируется в конструкторе класса приложения, как это показано ниже:

class newApplication : public application

{

public :

newApplication : application ("new program"), quitButton(this)

{ }

...

private:

quitButtonClass quitButton;

};

Обычно при нажатии на кнопку реакция заключается в вызове функции-члена класса приложения. Мы можем определить единственный класс общего назначения, который поддерживает это действие, и таким образом избежим необходимости определять новые классы для каждого типа кнопки. Поскольку C++ является языком со строгим контролем типов данных, новый класс должен использовать шаблон и параметризироваться с помощью нового класса приложения1. Шаблон выглядит следующим образом:

template

converted to PDF by BoJIoc

class tbutton : public button

{

public:

tbutton (window * win, char * t, int x, int y, int h, int w, void (T::*f)() )

: button(win, t, x, y, h, w), fun(f)

{ } protected:

void (T::* fun) ();

virtual void pressed (window * win)

{

(((T *) win)->*fun) ();

}

};

Последний из аргументов, f, служит указателем на функцию-член и должен соответствовать какому-нибудь методу класса Т. Мы должны признать, что синтаксис, используемый для описания указателя на функцию-член, является довольно бестолковым. Эта функция запоминается в переменной fun и вызывается при нажатии кнопки. С применением этого класса приложение с двумя кнопками может быть создано следующим образом:

class helloApp : public application

{

public: helloApp() :

application("hello world"),

quitButton (this, "quit", 5, 5, 50, 20, quit), clearButton (this, "clear", 5, 30, 50, 20,

clearAndUpdate) { };

virtual void mousButtonDown(int, int); private:

tbutton quitButton; tbutton clearButton;

};

19.5.2. Классы menu и menuItem

Меню во многих отношениях похожи на кнопки. В среде LAF существуют два класса для обслуживания меню: menu и menuItem. Первый класс представляет собой категорию линеек меню, а второй конкретный элемент этой категории. Когда пользователь указывает на меню, на экране высвечиваются соответствующие элементы меню. Когда мышью выбирается элемент меню, выполняется метод selected для элемента меню.

Нужное действие элемента меню обеспечивается за счет создания подкласса класса menuItem и переопределения метода selected. Это происходит так же, как и в случае с кнопками.

Меню обычно объявляются как поля данных в классе приложения и инициализируются конструктором, что иллюстрируется следующим примером:

сlass clearMenuItem : public menuItem

{

public:

clearMenuItem (menu & m, char * t) : menuItem(m, t) { }

protected:

virtual void selected (window *);

converted to PDF by BoJIoc

};

class helloApp : public application

{

public: helloApp ()

: application("hello world") clearMenu (this, "Clear"), clearItem (clearItem, "clear/C") { };

virtual void mouseButtonDown(int, int); private:

menu clearMenu; clearMenuItem clearItem;

};

void clearMenuItem::selected (window * w)

{

w->clear () ;

}

Класс tmenuItem аналогичен классу tbutton. Если вы помните, класс tbutton устраняет необходимость создания нового класса кнопок, так как все, что делает кнопка это вызывает функцию-член. Аналогичным образом класс tmenuItem наследует от класса menuItem и добавляет новый аргумент, который должен быть функцией-членом. Функция, передаваемая в качестве добавочного аргумента, должна вызываться при выборе соответствующего элемента меню.

template

class tmenuItem : public menuItem

{

public:

tmenuItem (menu & m, char * t, void (T::* f) () ) : menuitem(m, t), fun(f)

{ } protected:

void (T::* fun) ();

virtual void selected (window * win)

{

(((T*) win)->*fun)();

}

};

Прочие классы среды LAF позволяют программисту размещать в окне текстовые поля (в том числе редактируемые). Эти свойства среды LAF здесь не описаны: подробную документацию по среде LAF, а также исходные тексты можно найти по адресу ftp://ftp.cs.orst.edu/pub/budd/laf.

19.6. Резюме

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

Среды разработки предназначены для решения узкого круга проблем. В случае среды LAF — это создание простых однооконных приложений с кнопками и меню.

Среда обеспечивает общую структуру программы, однако опускает все конкретные детали. В случае среды LAF определяется цикл, управляемый