Листинг 1. Команда трансляции программы
Курсовая работа по дисциплине
Постановка задачи Используя предоставленную документацию реализовать класс Object. Создать двух наследников класс Rect и класс Text. Класс Rect представляет собой прямоугольник. Класс Text представляет собой строку текста. Классы Rect и Text можно отрисовать в окне. Необходимо создать окно и отрисовать в нем прямоугольник и текст. Прямоугольник должен иметь высоту окна и 1/3 его ширины. Текст должен располагаться по центру окна. При изменении размеров окна должны изменяться размеры прямоугольника и положение текста. Размер текста всегда остается неизменным. 1 Алгоритм решения задачи Для решения задачи был использован паттерн «Компоновщик» и разработаны следующие классы: ¾ Object – класс, который реализует вырожденный случай паттерна «Компоновщик». Он выступает в качестве Component, Leaf и Composite; ¾ XWindow – класс, реализующий функциональность окна в оконной системе X Window System; ¾ Text – класс, реализующий хранение и рисование текста посередине экрана; ¾ Rect – класс, реализующий рисование прямоугольника необходимого размера и положения; 2 Решение задачи 2.1 Класс Object Выступая в роли участника Component, этот класс реализует следующие методы: · Operation () – findChild () – в результате вызова метод возвращает 0; · Operation () – draw () – ничего не делает; · Add () – setParent (); · Remove () – SetParent (); · GetChild () – findChild () – в результате вызова метод возвращает 0; Функция setParent () устанавливает родителя объекта и добавляет объект в список дочерних объектов родителя. Если у объекта уже есть родитель, то вначале объект удаляется из списка дочерних объектов старого родителя. Чтобы указать, что у объекта нет родителя, параметром метода надо передать NULL. Таким образом, этот метод реализует функционал методов Add () и Remove ().
2.2 Классы Text и Rect Эти классы выступают в роли Leaf, наследуют от Component и определяют следующие методы: · Operation () – findChild () –проверяет переданное имя со своим собственным; · Operation () – draw () – выполняет собственную отрисовку на экране; Класс Text рисует хранящийся в нем текст посередине окна. Класс Rect рисует треугольник, находящийся у левого края окна, шириной в треть ширины окна и высотой равной высоте окна. 2.3 Класс XWindow Этот класс выступает в роли участника Composite, наследует от Component и определяет следующие методы: · Operation () – findChild () – проверяет имена всех дочерних объектов; · Operation () – draw () – рисует себя на экране, затем вызывает метод draw () у всех дочерних объектов: · GetChild () – findChild () – в качестве основного метода использует метод findChild (), он же позволяет индексировать дочерние объекты; · void Open () – создает и выводит на экран окно приложения; · void Close () – закрывает окно; После открытия вызывается функция отрисовки, затем объект ожидает сообщений об изменение размера окна и выполняет перерисовку своего содержимого в соответствие с новыми размерами окна. В случае получения сообщения о закрытие пользователем окна, ожидание новых сообщений прекращается и окно удаляется. 3 Структура программного кода Текст программы расположен в следующих файлах: · object.h и object.cpp – определение и реализация класса Object; · text.h и text.cpp – определение и реализация класса Text; · rect.h и rect.cpp – определение и реализация класса Rect; · window.h и window.cpp – определение и реализация класса XWindow; · main.cpp – главная функция main;
4 Трансляция программы Трансляция программы осуществляется из директории, в которой находятся файлы с исходным кодом. Команда для трансляции приведена в листинге 1.
Листинг 1. Команда трансляции программы fox@lepihin:~/Documents/workspace/project740$ g++ -o win main.cpp window.cpp object.cpp rect.cpp text.cpp -lX11 5 Тестирование Для тестирования программы запустим ее и попробуем изменить размер окна. На рисунке 1 приведено изображения окна до изменения его размера, на рисунке 2 – после. . Рисунок 1 - Окно до изменения его размера
Рисунок 2 – Окно после изменения его размера
Приложение А Полный текст программ с комментариями. Листинг 1. Файл object.h #ifndef OBJECT_H #define OBJECT_H
#include <list> #include <string>
namespace ikita {
class Object { Object * _parent; std::list<Object *> _children; std::string _name; public: Object (Object * parent = NULL); virtual ~Object () = 0;
Object * parent () const; void setParent (Object *); const std::list<Object *> & children () const; Object * findChild (const std::string & name); std::string objectName () const; void setObjectName (const std::string & name);
virtual void draw (); }; }
#endif // OBJECT_H
Листинг 2. Файл object.cpp #include "object.h"
using namespace std;
namespace ikita {
Object::Object (Object * _parent): _parent (_parent) { }
Object::~Object () { }
Object * Object::parent () const { return _parent; }
void Object::setParent (Object * _p) { // если есть родитель, то удалится из списка его детей if (_parent!= NULL) { _parent->_children.remove (this); } // если в качестве нового родителя передан не нулевой указатель, то // добавить себя в список его детей if (_p!= NULL) { _p->_children.push_back (this); } _parent = _p; }
const std::list<Object *> & Object::children () const { // вернуть список дочерних объектов return _children; }
Object * Object::findChild (const std::string &) { // вернуть нулевой указатель return NULL; }
string Object::objectName () const { // вернуть имя объекта return _name; }
void Object::setObjectName (const string & name) { // установить новое имя объекта _name = name; }
void Object::draw () { // ничего не делать } }
Листинг 3. Файл window.h #ifndef WINDOW_H #define WINDOW_H
#include <X11/Xlib.h>
#include "object.h"
namespace ikita { class XWindow: public Object { Display * display; Window window; GC gr_context; int width; int height; public: XWindow ();
void Open (); void Close ();
Display * getDisplay () { return display; }
Window getWindow () const { return window; }
int getHeight () const { return height; }
int getWidth () const { return width; }
GC getGContext () const { return gr_context;
}
virtual void draw (); }; } /* namespace ikita */
#endif
Листинг 4. Файл window.cpp #include "window.h"
#include <iostream>
using namespace std;
namespace ikita { XWindow::XWindow (): display (NULL) { }
void XWindow::Open() { // проверить, окно не создано if (display!= NULL) { return; } // установить ширину и высоту окна по-умолчанию width = 800; height = 600; // установить позицию окна и ширину бордюра по-умолчанию unsigned winX = 0, winY = 0, winBorderWidth = 0; // присоединится к дисплею display = XOpenDisplay(NULL); if (display == NULL) { cerr << "Cannot connect to X server\n"; return; } // получить номер экрана по-умолчанию const int screen_num = DefaultScreen(display); // создать простое окно window = XCreateSimpleWindow( display, RootWindow(display, screen_num), winX, winY, width, height, winBorderWidth, BlackPixel(display, screen_num), WhitePixel(display, screen_num)); // задать имя окна XStoreName(display, window, "Example"); // вывести окно на экран XMapWindow(display, window); // настроить параметры отрисовки примитивов XGCValues gr_values; gr_values.line_width = 1; gr_values.line_style = LineSolid; // получить графический контекст для рисования gr_context = XCreateGC(display, window, GCLineWidth | GCLineStyle, &gr_values); // установить список ожидаемых типов сообщений XSelectInput(display, window, ExposureMask | StructureNotifyMask); // синхронизировать дисплей XFlush(display); // объект структуры для приходящих сообщений XEvent event; // добавить в список принимаемых типов сообщений // сообщение о нажатие на кнопку закрытия окна Atom wmDelete = XInternAtom(display, "WM_DELETE_WINDOW", True); XSetWMProtocols(display, window, &wmDelete, 1); bool repeat = true; // выполнить отрисовку содержимого окна draw (); while (repeat) { // получить следующее сообщение XNextEvent(display, &event); switch (event.type) { case Expose: // сообщение о том, что содержимое окна надо перерисовать draw (); break; case ConfigureNotify: { // сообщение об изменение геометрии окна XConfigureEvent xce = event.xconfigure; // установить новые размеры окна width = xce.width; height = xce.height; break; } case ClientMessage: // получено клиентское сообщение, на которое мы ранее подписались // прекратить цикл repeat = false; break; } } }
void XWindow::Close () { // проверить, что окно открыто if (display == NULL) { return; } // удалить окно XDestroyWindow(display, window); // синхронизовать дисплей XFlush(display); // отсоединится от дисплея XCloseDisplay(display); // указатель на дисплей приравнять к нулевому указателю
display = NULL; }
void XWindow::draw() { // очистить окно XClearWindow (display, window); // отрисовать все дочерние объекты for (list<Object *>::const_iterator it = children ().begin (); it!= children ().end (); ++it) { (*it)->draw (); } } }
Листинг 5. Файл rect.h #ifndef RECT_H #define RECT_H
#include "object.h"
#include <string>
namespace ikita {
class XWindow;
class Rect: public Object { XWindow * win; public: Rect (XWindow * _win); virtual ~Rect () {}
virtual Object * findChild (const std::string & name); virtual void draw (); };
}
#endif // RECT_H
Листинг 6. Файл rect.cpp #include "rect.h"
#include "window.h" #include <X11/Xlib.h>
namespace ikita {
Rect::Rect (XWindow * _win): win (_win) { // установить имя объекта setObjectName ("rectangle"); }
Object * Rect::findChild (const std::string & name) { // сравнить переданное имя со своим и в случае совпадения // вернуть указатель на себя, иначе вернуть нулевой указатель if (Object::objectName () == name) { return this; } else { return NULL; } }
void Rect::draw () { // нарисовать прямоугольник вдоль левого края окна // с шириной равно трети ширины окна // и высотой равно высоте окна XDrawRectangle (win->getDisplay (), win->getWindow (), win->getGContext (), 0, 0, win->getWidth () / 3, win->getHeight ()); } }
Листинг 7. Файл text.h #ifndef TEXT_H #define TEXT_H
#include "object.h"
namespace ikita {
class XWindow;
class Text: public Object { XWindow * win; std::string str; public: Text (XWindow * _win, std::string _str); virtual ~Text () {}
virtual Object * findChild (const std::string & name); virtual void draw (); };
}
#endif // TEXT_H
Листинг 8. Файл text.cpp #include "text.h" #include "window.h"
namespace ikita {
Text::Text (XWindow * _win, std::string _str): win (_win), str (_str) { setObjectName ("text"); }
Object * Text::findChild (const std::string & name) { // сравнить переданное имя со своим и в случае совпадения // вернуть указатель на себя, иначе вернуть нулевой указатель if (Object::objectName () == name) { return this; } else { return NULL; } }
void Text::draw () { // получить графический контекст для отрисовки примитивов GContext gc_id = XGContextFromGC (win->getGContext ()); // получить шрифт для отрисовки текста XFontStruct * font = XQueryFont (win->getDisplay (), gc_id); // расчитать ширину текста в пикселях int text_width = XTextWidth (font, str.c_str (), str.size ()); // отрисовать текст по середине окна XDrawString(win->getDisplay (), win->getWindow (), win->getGContext (), (win->getWidth () - text_width) / 2, win->getHeight () / 2, str.c_str (), str.size ()); } }
Листинг 9. Файл main.cpp #include "window.h" #include "rect.h" #include "text.h"
int main() { // создать окно ikita::XWindow win; // создать прямоугольник ikita::Rect rect (&win); // создать объект класса Text ikita::Text text (&win, "hello world"); // установить родителей rect.setParent (&win); text.setParent (&win); // открыть окно win.Open (); // закрыть окно win.Close (); }
Воспользуйтесь поиском по сайту: ©2015 - 2024 megalektsii.ru Все авторские права принадлежат авторам лекционных материалов. Обратная связь с нами...
|