БГУ Пособие - Программирование в C++ Builder. Учебное пособие по курсу методы программирования для студентов специальностей
Скачать 1.24 Mb.
|
Графические файлы. Приложения C++Builder поддерживают за- грузку и сохранение рисунков и графиков в файлах изображений. Для за- грузки изображения из файла можно использовать метод LoadFromFile(). Чтобы сохранить изображение в файле, используется метод SaveToFile(). Единственным параметром этих методов является имя файла. Рисунок распознает стандартное расширение файлов битовых образов .bmp и соз- дает свою графику как объект класса TBitmap, а затем вызывает метод LoadFromFile загрузки изображения из файла с указанным именем. Ниже приводится пример приложения, иллюстрирующего работу с графическим компонентом TImage. На рис. 18 приведена форма прило- жения в процессе проектирования. Рис. 18. Форма в процессе проектирования // Обработчик событий для перемещения мыши по // компоненту Image1 void __fastcall TForm1::Image1MouseMove(TObject *Sender, TShiftState Shift, int X, int Y) { if( (Shift.Contains(ssLeft)) && (drawFlag) ) Image1->Canvas->LineTo(X,Y); else Image1->Canvas->MoveTo(X,Y); } //--------------------------------------------------------------------------- // Обработчик события нажатия на клавишу мыши void __fastcall TForm1::Image1MouseDown(TObject *Sender, TMouseButton Button, TShiftState Shift, int X, int Y) {drawFlag=true; } 70 //--------------------------------------------------------------------------- // Обработчик события отпускания клавиши мыши void __fastcall TForm1::Image1MouseUp(TObject *Sender, TMouseButton Button, TShiftState Shift, int X, int Y) { drawFlag=false; } //--------------------------------------------------------------------------- // Обработчик события для кнопки Close void __fastcall TForm1::Button1Click(TObject *Sender) { Close(); } //--------------------------------------------------------------------------- // Обработчик события для кнопки Color void __fastcall TForm1::Button2Click(TObject *Sender) { if( ColorDialog1->Execute()) Image1->Canvas->Pen->Color = ColorDialog1->Color; } //--------------------------------------------------------------------------- // Обработчик события для кнопки LoadPicture void __fastcall TForm1::Button3Click(TObject *Sender) { if (OpenDialog1->Execute()) Image1->Picture->LoadFromFile( OpenDialog1->FileName ); } //--------------------------------------------------------------------------- // Обработчик события для кнопки SavePicture void __fastcall TForm1::Button4Click(TObject *Sender) { if (SaveDialog1->Execute()) Image1->Picture->SaveToFile( SaveDialog1->FileName ); } //--------------------------------------------------------------------------- // Обработчик изменений в компоненте CSpinEdit1 void __fastcall TForm1::CSpinEdit1Change(TObject *Sender) { Image1->Canvas->Pen->Width= CSpinEdit1->Value; } Обслуживание палитр. Компонентам, содержащим графические изображения, может потребоваться взаимодействие с Windows и экран- ным драйвером, чтобы обеспечить надлежащее отображение данных компонентов. Реализация палитр призвана обеспечить, чтобы самое верхнее активное окно использовало полную цветовую палитру, в то время как фоновые окна максимально использовали оставшиеся цвета палитр. C++Builder не содержит самостоятельных средств для создания и об- служивания иных палитр, кроме палитры битовых образов. Однако, можно получить дескриптор некоторой палитры с помощью метода Get- Palette(), а затем воспользоваться методом Windows API CreatePalette(). 71 Компоненты C++Builder автоматически поддерживают механизм реали- зации палитр. Таким образом, если компонент имеет палитру, вы може- те воспользоваться двумя методами GetPalette() и PaletteChanged(), на- следованными от базового компонентного класса TControl, чтобы управ- лять тем, как Windows обращается с этой палитрой. Когда ваш компонент ассоциируется с некоторой палитрой посредст- вом перегрузки метода GetPalette(), C++Builder автоматически берет на себя реакцию на сообщения Windows от палитр с помощью метода PaletteChanged(). Внеэкранные битовые образы. Методика программирования гра- фических приложений заключается в создании внеэкранного битового образа, заполнении его конкретным изображением и копировании изо- бражения из битового образа в экранное окно. Благодаря этому умень- шается заметное глазу мерцание экрана монитора, вызванное повторным рисованием непосредственно в экранном окне. C++Builder позволяет создавать объекты класса TBitmap для представления изображений фай- лов и других ресурсов, которые также способны работать как внеэкран- ные изображения. C++Builder предусматривает четыре способа копирования изображе- ний, которые приведены в табл. 8. Таблица 8 Требуемый результат Метод Полное копирование графики Draw Копирование с масштабированием StretchDraw Копирование прямоугольного участка канвы CopyRect Копирование с растровыми операциями BrushCopy Далее приводится пример копирования изображения в обработчике события для кнопки: void __fastcall TForm1::Button1Click(TObject *Sender) { Graphics::TBitmap *pBitmap = new Graphics::TBitmap(); try { pBitmap->LoadFromFile("C:\\factory.bmp "); pBitmap->Transparent = true; pBitmap->TransparentColor = pBitmap->Canvas->Pixels[50,50]; Form1->Canvas->Draw(0,0,pBitmap); pBitmap->TransparentMode = tmAuto; Form1->Canvas->Draw(50,50,pBitmap); } catch (...) {ShowMessage("Нельзя загрузить или отобразить изображение"); } delete pBitmap; 72 } Анимация. Для воспроизведения анимации, состоящей в последова- тельном отображении кадров из стандартных avi-файлов Windows ис- пользуется компонент Animate из страницы Win32 Палитры компонен- тов. Последовательность действий может быть следующей: Animate1->FileName=”p.avi”; Animate1->play(1, Animate1->FrameCount,1); Animate1->stop(); Для обеспечения процесса мультимедиа и воспроизведения звука и анимации при отображении war-, rmi-, mid-файлов используется компо- нент MediaPlayer(страница System). При анимации широко используется невидимый компонент Timer. При этом в одном из методов, например FormCreate() или Button1Click(), устанавливается частота прерывания: Timer1->Interval=time; Компонент Timer генерирует событие OnTimer, в обработчике кото- рого осуществляется перерисовка. Вопросы 1. Как установить режимы рисования на канве? Какие режимы есть у пера? 2. Как очистить поверхность графического компонента Image? 3. Как установить цвет и ширину линии, которой рисуется график функции? 4. Назовите основные методы для рисования класса Canvas. 5. Назовите основные события графических компонентов Image и PaintBox. 6. Как вывести текст в графические компоненты? 7. Как вывести на графическом экране: a) точку в позицию, указанную курсором мыши; б) свою фотографию, загруженную из графического файла; в) установить толщину линии, ее цвет и провести линию указанной длины и под заданным углом. 8. Как установить цвет рисунка при использовании графики и нари- совать указанным цветом две касающихся внутренним образом окруж- ности? 9. Опишите методику анимации изображения. 10. Какой режим пера Pen используется для удаления рисунка при повторном его рисовании? 11. Какие свойства имеет компонент Timer? 12. Назовите основные события мыши. 73 13. Как в программе распознать координаты курсора мыши? 14. Как распознать нажатую кнопку мыши? 15. Когда наступают события мыши OnStartDrag, OnDragOver, OnDragDrop, OnEndDrag? Что можно распознать при обработке этих со- бытий? 16. С помощью какой клавиши клавиатуры можно перемещать фокус с элемента на элемент? 17. Какие способы вывода графической информации Вы знаете? 18. Какие проблемы могут возникнуть при рисовании непосредствен- но на форме? Как их преодолеть? Почему такие проблемы не возникают при использовании компонента Image? 19. С помощью какого метода класса Canvas можно вывести текст? Упражнения 1. Нарисовать график функции y=sin x. 2. Нарисовать график функции y=-2x 2 +3x. 3. Вывести аналоговые часы (со стрелками). Предусмотреть кнопку для запуска и остановки часов. Использовать функцию Time() и класс TDataTime для получения текущего времени. 4. “Летающий” шарик. По достижении границы компонента он отра- жается от границы по правилам отражения. Предусмотреть кнопку оста- новки и запуска шарика. 5. Точка равномерно движется по окружности. Предусмотреть воз- можность увеличения скорости движения. 6. Построить простейший графический редактор с возможностью вы- бора цвета рисования. 7. Равносторонний треугольник вращается вокруг своего центра. Предусмотреть возможность увеличения скорости вращения. 8. Изобразить прямоугольник (квадрат), вращающийся вокруг своего центра. Предусмотреть возможность увеличения скорости вращения. 9. Вращаются два отрезка, каждый вокруг своей концевой точки. Предусмотреть возможность изменения скорости вращения каждого от- резка отдельно. 10. “Ипподром”. Играющий выбирает одну из трех лошадей, состя- зающихся на бегах, и выигрывает, если его лошадь приходит первой. Скорость передвижения лошадей на разных этапах выбирается програм- мой с помощью датчика случайных чисел. 11. Игра в слова. Программа выбирает слово и рисует на экране столько прочерков, сколько букв в слове. Отгадать, какое слово загадано 74 программой. За один ход играющий указывает одну букву. Если буква не угадана, то играющий теряет одно очко. В начальный момент у играю- щего 15 очков. 12. Требуется ввести курсор в область экрана (небольшой круг), рас- положение которого неизвестно играющему. Если курсор приближается к области, то его цвет становится ярче, если удаляется, то тускнеет. 5. РАБОТА С БАЗАМИ ДАННЫХ База данных – это поименованная совокупность взаимосвязанных данных, находящихся под управлением системы управления базами дан- ных (СУБД). Различают иерархические, сетевые и реляционные СУБД. В C++ Builder используется несколько механизмов и инструментов для ра- боты с базами данных: BDE (Borland Database Engine), ADO (ActiveX Data Object) позволяет коннектится к базам данных, используя объекты ActiveX, позволяет напрямую коннектится к базам данных поддержи- вающих InterBase. 5.1. Основные концепции реляционных баз данных Реляционная база данных представляет собой одну или совокупность взаимосвязанных таблиц, состоящих из записей. С позиции реляционной алгебры БД это совокупность отношений над n множествами M1, M2, ..., Mn. Например, это множества студентов, преподавателей, экзаменов. Отношение представляет собой таблицу. При этом наборы вида Для таблицы Student (табл. 9) первичным ключом может быть номер сту- денческого билета. Для ускорения доступа к данным по первичному ключу в СУБД имеется механизм, называемый индексированием. Индекс представляет собой древовидный список, указывающий на местополо- жение записи для каждого первичного ключа. Возможно индексирование отношения с использованием атрибутов, отличных от первичного ключа (вторичного ключа), например фамилии студента. 75 Таблица 9 (Student) Stud_Id StudName Kurs Address Predmet Prepod 111111 Котов П.А. 2 Витебск, Ленина 1 Prog Романчик 111112 Павлов А.И. 2 Минск, Репина 2 Matan Примачук 111113 Коваль Н.К. 1 Гомель,Пушкина 3 Difur Громак Для поддержания ссылочной целостности данных в нескольких взаи- мосвязанных таблицах используется механизм внешних ключей. При этом некоему атрибуту одного отношения назначается ссылка на пер- вичный ключ другого отношения; тем самым закрепляются связи подчи- ненности между этими отношениями. При этом отношение, на первич- ный ключ которого ссылается внешний ключ другого отношения, назы- вается master-отношением, а отношение, от которого исходит ссылка, на- зывается detail-отношением, или подчиненным отношением. После на- значения такой ссылки СУБД имеет возможность автоматически отсле- живать вопросы “ненарушения“ связей между отношениями. Если дела- ется попытка вставить в подчиненную таблицу запись, для внешнего ключа которой не существует соответствия в главной таблице, СУБД сгенерирует ошибку. Если попытаться удалить из главной таблицы за- пись, на первичный ключ которой имеется ссылка из подчиненной таб- лицы, или изменить первичный ключ, СУБД также сгенерирует ошибку. Существуют два подхода к удалению и изменению записей из главной таблицы: 1) Запретить удаление всех записей, а также изменение первичных ключей главной таблицы, на которые имеются ссылки подчиненной таб- лицы. 2) Распространить всякие изменения в первичном ключе главной таб- лицы на подчиненную таблицу. 5.2. Проектирование баз данных Проектирование базы данных (БД) можно представить в виде сле- дующей последовательности шагов: 1. Разработка модели БД, которая включает в себя: идентификацию функциональной деятельности предметной области; идентификацию объектов, которые осуществляют эту деятельность; идентификацию взаимосвязей между объектами. 2. Определение атрибутов, которые уникальным образом идентифи- цируют каждый объект (первичный ключ). Первичный ключ гарантиру- ет, что в таблице не будет содержаться двух одинаковых строк. 76 3. Устанавливание связи между объектами и проведение операции исключения избыточности данных – нормализация таблиц. Таким образом, для проектируемой базы данных сначала определя- ются таблицы, поля, индексы и связи между таблицами Существует несколько типов связей между таблицами: “один-к- одному”, “один-ко-многим”, “многие-ко-многим”. Связь “один-к- одному” представляет собой простейший вид связи данных, когда пер- вичный ключ таблицы является внешним ключом, ссылающимся на пер- вичный ключ другой таблицы. Связь “один-ко-многим” отражает реаль- ную взаимосвязь в предметной области. Эта связь описывает механизм классификаторов или кодов. Например, 01.01 – математика. Связь “мно- гие-ко-многим” в явном виде в реляционных базах данных не поддержи- вается. Процесс нормализации. После разработки структуры таблиц проек- тируемую базу данных следует проанализировать, используя правила нормализации. Нормализация заключается в приведении таблиц к нор- мальным формам. Этот процесс включает: устранение повторяющихся групп (приведение к первой нормальной форме), удаление частично за- висимых атрибутов (приведение ко второй нормальной форме), удаление транзитивно зависимых атрибутов (приведение к третьей нормальной форме). На практике используется не более трех первых нормальных форм – следует учитывать время, необходимое для “соединения” таблиц при отображении на экране. После применения правил нормализации логи- ческие группы данных располагаются не более чем в одной таблице. На пересечении каждой строки и столбца таблицы всегда находится единст- венное значение. Приведение к первой нормальной форме. Если поле в данной за- писи содержит более одного значения, такие группы данных называются повторяющимися. Первая нормальная форма не допускает наличия таких многозначных полей. Рассмотрим пример БД, содержащей таблицу Stu- dent (табл. 10; номер студенческого билета является первичным ключом). Для приведения таблицы к первой нормальной форме мы должны поле Address разбить на два поля, содержащие город и улицу, если в даль- нейшем будет выполняться обработка данных по регионам. Приведение ко второй нормальной форме. Следующий шаг в про- цессе нормализации состоит в удалении всех неключевых атрибутов, ко- торые зависят только от части первичного ключа. Такие атрибуты назы- ваются частично зависимыми. Для приведения таблицы ко второй нор- мальной форме удалим из нее атрибуты Predmet и Prepod и создадим две 77 таблицы (табл. 11 и 12), которые будут содержать только эти атрибуты, и они же будут составлять их первичный ключ. Таблица 10 (Student) Stud_Id StudName Kurs City Street 111111 Котов П.А. 2 Витебск Ленина 1 111112 Павлов А.И. 2 Минск Репина 2 111113 Коваль Н.К. 1 Гомель Пушкина 3 Таблица 11 (Subject) Subj_Id Subj_Name Hour 10 Prog 120 20 Matan 180 30 Difur 70 Таблица 12 (Prepod) Prepod_Id Prepod_Name 11 Романчик 20 Примачук 32 Громак Кроме этого будем использовать также таблицу Exams (табл. 13). Таблица 13 (Exams) Exam _Id Stud_Id Subj_Id Exammark ExamDate 23 111111 10 8 6/01/06 34 111112 20 6 10/01/06 42 311113 30 3 20/01/06 Приведение к третьей нормальной форме. Третий этап процесса приведения таблиц к нормальной форме состоит в удалении всех неклю- чевых атрибутов, которые зависят от других неключевых атрибутов или вычисляются по ним. Каждый неключевой атрибут должен быть логиче- ски связан с атрибутом, являющимся первичным ключом. Например, из таблицы можно удалить атрибут Stipend. Получим табл. 14. Таблица 14 (Stipend) Stud_Name Summa Котов П.А. 120 Павлов А.И. 130 Коваль Н.К. 100 Добавим таблицу, связывающую преподавателей и предметы (табл. 15). 78 Таблица 15 (Sub_Prepod) Prepod_Id Subj_Id 11 10 32 20 43 30 Разбиение информации на мелкие единицы способствует повышению надежности базы данных, но снижает ее производительность. На последнем шаге разработки БД необходимо спланировать вопро- сы безопасности и конфиденциальности информации и определить права на использование и на модификацию данных. Теперь можно приступать к созданию приложений, работающих с ба- зами данных. Рассмотрим сначала средства для разработки таблиц. |