Заглавная страница Избранные статьи Случайная статья Познавательные статьи Новые добавления Обратная связь FAQ Написать работу КАТЕГОРИИ: АрхеологияБиология Генетика География Информатика История Логика Маркетинг Математика Менеджмент Механика Педагогика Религия Социология Технологии Физика Философия Финансы Химия Экология ТОП 10 на сайте Приготовление дезинфицирующих растворов различной концентрацииТехника нижней прямой подачи мяча. Франко-прусская война (причины и последствия) Организация работы процедурного кабинета Смысловое и механическое запоминание, их место и роль в усвоении знаний Коммуникативные барьеры и пути их преодоления Обработка изделий медицинского назначения многократного применения Образцы текста публицистического стиля Четыре типа изменения баланса Задачи с ответами для Всероссийской олимпиады по праву Мы поможем в написании ваших работ! ЗНАЕТЕ ЛИ ВЫ?
Влияние общества на человека
Приготовление дезинфицирующих растворов различной концентрации Практические работы по географии для 6 класса Организация работы процедурного кабинета Изменения в неживой природе осенью Уборка процедурного кабинета Сольфеджио. Все правила по сольфеджио Балочные системы. Определение реакций опор и моментов защемления |
В объектно-ориентированных языкахСодержание книги Поиск на нашем сайте
В объектно-ориентированных языках класс является абстрактным типом данных.[Прим. 1] Полиморфизм реализуется с помощью наследования классов и виртуальных функций. Класс-потомок наследует сигнатуры методов класса-родителя, а реализация, в результате переопределения метода, этих методов может быть другой, соответствующей специфике класса-потомка. Другие функции могут работать с объектом как с экземпляром класса-родителя, но если при этом объект на самом деле является экземпляром класса-потомка, то во время исполнения будет вызван метод, переопределенный в классе-потомке. Это называется поздним связыванием. [Примером использования может служить обработка массива, содержащего экземпляры как класса-родителя, так и класса-потомка: очевидно, что такой массив может быть объявлен только как массив типа класса-родителя и у объектов массива могут вызываться только методы этого класса, но если в классе-потомке какие-то методы были переопределены, то в режиме исполнения для экземпляров этого класса будут вызваны именно они, а не методы класса-родителя.] Класс-потомок сам может быть родителем. Это позволяет строить сложные схемы наследования — древовидные или сетевидные. Абстрактные (или чисто виртуальные) методы не имеют реализации вообще (на самом деле некоторые языки, например C++, допускают реализацию абстрактных методов в родительском классе). Они специально предназначены для наследования. Их реализация должна быть определена в классах-потомках. Класс может наследовать функциональность от нескольких классов. Это называется множественным наследованием. Множественное наследование создаёт известную проблему (в C++), когда класс наследуется от нескольких классов-посредников, которые в свою очередь наследуются от одного класса (так называемая «Проблема ромба»): если метод общего предка был переопределён в посредниках, неизвестно, какую реализацию метода должен наследовать общий потомок. Решается эта проблема путём отказа от множественного наследования для классов и разрешением множественного наследования для полностью абстрактных классов (то есть интерфейсов) (C#, Delphi,Java), либо через виртуальное наследование (C++). Динамическое создание объектов на форме с помощью классов. Статья посвящена динамическому созданию обычных и визуальных объектов, а также наследованию объктов Задача формулируется следующим образом- дан целочисленный массив содержимого формы:0- combobox,1-spinedit,2-edit,3 и 4-panel,необходимо создать эти различные объекты на форме или на панелях, для удобства доступа к ним. Естественно предложить решение без динамического создания- размещаем объекты на форме, устанавливаем единый обработчик события (так как формат обработчиков одинаков-один параметр Sender:TObject, то такое возможно), а в свойстве Tag объектов храним его id(не номер типа а номер объекта в массиве), для каждого значения tag исполняем то же код. Однако же если массив двумерный как в редакторе кампаний hi, то сложно использовать этот метод, а если формат размещен в файле, базе данных или присваивается при выполении программы то без динамических объектов не обойтись. Пример использовался для написания редактора кампаний, когда разные свойства требовали разных объектов, например количество сценариев требовало наличие spinedit,для названия кампании нужен edit,а для имен файлов карт panel, и не простая, а чтобы при клике вызывался opendialog. Как это делается: Во первый объявляем саму структуру объектов - у нас будет двумерный массив объектов, двумерный массив подписей к нему, одномерный массив панелей для объектов и также хранится массив количества свойств(для двумерных массивов, например свойств кампании всего 2, а свойств сценариев уже 5). tcampa_struct=class num:array[0..2] of array of integer; p:array[0..2]of TPanel; l:array[0..2]of array of TLabel; wc:array[0..2] of array of TWinControl; constructor Create(Sender:TObject); destructor Free; end;Теперь опишем как создавать объекты. Сначала обратим внимание на TwinControl -это наибольший предок всех,используемых мною, объектов. Для любого объекта в delphi необходимо сделать такое присвоение: object:=TObject.Create();, то есть создать экземляр класса, далее для визуальных объектов необходимо присвоить родителя object.parent:=hisparent; после этого объект создастся со свойствами по умолчанию, а затем нужно присвоить часть свойств нужным вам значениям. Я изменяю размер и расположение объектов. В зависимости от типа объекта конструкторы разные и вызываются дочерние: wc[i,j]:=TComboBox.Create(p[i]); constructor tcampa_struct.Create(Sender:TObject);var i,j:integer;beginfor i:=0 to 2 do begin setlength(num[i],campa_structC[i]); setlength(l[i],campa_structC[i]); setlength(wc[i],campa_structC[i]); end; num[0,0]:=2;num[0,1]:=1;num[1,0]:=2;num[1,1]:=3;num[1,2]:=4;num[1,3]:=1;num[1,4]:=1;num[2,0]:=0;num[2,1]:=0;num[2,2]:=1;num[2,3]:=0;num[2,4]:=1; for i:=0 to 2 do begin p[i]:=TPanel.Create(TComponent(Sender)); p[i].Parent:=TWinControl(Sender); p[i].Left:=500; p[i].Width:=340; p[i].Height:=30*campa_structC[i]; end;p[0].Top:=60;p[1].Top:=130;p[2].Top:=300; for i:=0 to 2 do for j:=0 to campa_structC[i]-1 do begin l[i,j]:=TLabel.Create(p[i]); l[i,j].Parent:=p[i]; l[i,j].Left:=2; l[i,j].Top:=j*30+2; l[i,j].Height:=28; l[i,j].Width:=166; end; for i:=0 to 2 do for j:=0 to campa_structC[i]-1 do begin case num[i,j] of 0:wc[i,j]:=TComboBox.Create(p[i]); 1:wc[i,j]:=TSpinEdit.Create(p[i]); 2:wc[i,j]:=TEdit.Create(p[i]); 3:wc[i,j]:=TPanel.Create(p[i]); 4:wc[i,j]:=TPanel.Create(p[i]); end; wc[i,j].Parent:=p[i]; wc[i,j].Left:=172; wc[i,j].Top:=j*30; wc[i,j].Height:=25; wc[i,j].Width:=166; end; l[0,0].Caption:='Название';l[0,1].Caption:='Количество сценариев'; l[1,0].Caption:='Имя сценария';l[1,1].Caption:='Имя файла';l[1,2].Caption:='Имя ИИ файла';l[1,3].Caption:='Главный игрок';l[1,4].Caption:='Количество бонусов'; l[2,0].Caption:='Номер';l[2,1].Caption:='Уточненный номер';l[2,2].Caption:='Значение';l[2,3].Caption:='Тип адресата';l[2,4].Caption:='Номер адресата';end;Все создано кроме небольших оговорок необходимо присвоить события и некоторые начальные значение, скажем номер игрока не должен выходить за пределы 1 до 8. События для объектов должны быть тоже объявлены в форме. Вот я вызываю при клике на панель раличные opendialog и пишу имя файла в название. При закрытии формы не забываем вызвать деструктор. destructor tcampa_struct.free();var i,j:integer;beginfor i:=0 to 2 do for j:=0 to campa_structC[i]-1 do begin l[i,j].Free; wc[i,j].Free; end;for i:=0 to 2 do p[i].Free;end;Данная процедура в дополнении к конструктору. Обратим внимание на приведение к дочерним типам TcomboBox(Campa_struct.wc[2,3]). procedure TFormC1.CS_init;var i,j:integer;beginTPanel(Campa_struct.wc[1,1]).OnClick:=him_click;TPanel(Campa_struct.wc[1,2]).OnClick:=hiai_click;TSpinEdit(Campa_struct.wc[1,3]).Value:=1;TSpinEdit(Campa_struct.wc[1,3]).MinValue:=1;TSpinEdit(Campa_struct.wc[1,3]).MaxValue:=8;ReadFiles; TComboBox(Campa_struct.wc[2,3]).Clear;for i:=0 to 8 do TComboBox(Campa_struct.wc[2,3]).Items.Add(campa_actors[i]);TComboBox(Campa_struct.wc[2,3]).OnChange:=Campa_change_actor;TComboBox(Campa_struct.wc[2,0]).OnChange:=Campa_change_actor2;end;Классы Для поддержки ООП в язык Delphi введены объектные типы данных, с помощью которых одновременно описываются данные и операции над ними. Объектные типы данных называют классами, а их экземпляры — объектами. Классы объектов определяются в секции type глобального блока. Описание класса начинается с ключевого слова class и заканчивается ключевым словом end. По форме объявления классы похожи на обычные записи, но помимо полей данных могут содержать объявления пользовательских процедур и функций. Такие процедуры и функции обобщенно называют методами, они предназначены для выполнения над объектами различных операций. Приведем пример объявления класса, который предназначен для чтения текстового файла в формате "delimited text" (файл в таком формате представляет собой последовательность строк; каждая строка состоит из значений, которые отделены друг от друга символом-разделителем):
Класс содержит поля (FileVar, Items, Delimiter) и методы (PutItem, SetActive, ParseLine, NextLine, GetEndOfFile). Заголовки методов, (всегда) следующие за списком полей, играют роль упреждающих (forward) описаний. Программный код методов пишется отдельно от определения класса и будет приведен позже. Класс обычно описывает сущность, моделируемую в программе. Например, класс TDelimitedReader представляет собой "читатель" текстового файла с разбором считываемых строк на элементы (подстроки), которые отделены друг от друга некоторым символом, называемым разделителем. Класс содержит несколько полей:
Класс также содержит ряд методов (процедур и функций):
Обратите внимание, что приведенное выше описание является ничем иным, как декларацией интерфейса для работы с объектами класса TDelimitedReader. Реализация методов PutItem, SetActive, ParseLine, NextLine и GetEndOfFile на данный момент отсутствует, однако для создания и использования экземпляров класса она пока и не нужна. В некотором смысле объекты похожи на программные модули, для использования которых необходимо изучить лишь интерфейсную часть, раздел реализации для этого изучать не требуется. Поэтому дальше от описания класса мы перейдем не к реализации методов, а к созданию на их основе объектов. StringGrid.
Таблица StringGrid состоит из выделенных серым FixedCols и FixedRows - зафиксированных ячеек-заголовков, и обычных, белых ячеек. Содержимое Fixed ячеек недоступно редактированию, и меняется только программно. За возможность редактирования обычных ячеек отвечает одно из значений свойства Options. Итак, компонент StringGrid имеет возможность адресации каждой отдельной ячейки по номеру столбца и строки. Содержимое ячейки (i, j), где где i - номер столбца, j - номер строки, имеет вид StringGrid1.Cells [i, j] и доступно как для чтения, так и для записи. Здесь, как и всегда, номера столбцов (i) и строк (j) отсчитываются от 0. Выделенная ячейка таблицы имеет
поэтому содержимое выделенной ячейки будет адресоваться так: S:=StringGrid1.Cells[StringGrid1.Col, StringGrid1.Row]; Не правда ли, написание такой строки - утомительный процесс. Поэтому пользуйтесь оператором присоединения with: with StringGrid1 do
За многие свойства компонента Delphi StringGrid отвечает свойство Options. В Инспекторе Объектов Options - это раскрывающийся список, представляющий собой элементы данногомножества. Если значение элемента равно True, то он присутствует в множестве, если False - то нет.
StringGrid1.Options:=StringGrid1.Options+[goEditing]; //Включаем редактирование, другие элементы не трогаем StringGrid1.Options:=StringGrid1.Options-[goEditing]; //Выключаем редактирование, другие элементы не трогаем StringGrid1.Options:=[goEditing, goFixedVertLine, goFixedHorzLine, goVertLine, goHorzLine, goRowSelect]; //Задаём список необходимых элементов Если элементы заданы списком, это аналогично присвоению в Инспекторе Объектов этим элементам значения True, остальным - False. Ячеек в таблице, как правило, много, и в рамках компонента видна только часть из них. В программе доступна информация как об общем количестве строк и столбцов, так и номерах и количестве строк и столбцов, видимых в рамках таблицы. Количество строк в Delphi StringGrid равно StringGrid1.RowCount. Если ячейки не помещаются в таблице, появляются полосы прокрутки. При прокручивании
Отдельно требуется осветить вопрос очистки содержимого таблицы StringGrid. Так как таблица StringGrid, в отличие от, например, компонента Memo, не имеет метода для очистки содержимого сразу всех ячеек, то для удаления внесённых в таблицу ранее данных приходится очищать каждую ячейку отдельно. Делается это двумя вложенными циклами for, пробегающими по столбцам и строкам: var i, j: Integer; Хотя, оказывается, есть метод для очищения содержимого целого столбца или строки: StringGrid1.Cols[i].Clear; //Очищается столбец с номером i Очевидно, очищение этими методами гораздо быстрее. Однако будут очищены и ячейки фиксированной зоны, содержащие, например, названия строк и столбцов, которые удалять не нужно. Их после очистки нужно просто "написать" заново, на глаз эта манипуляция совершенно незаметна. Для очистки всей таблицы достаточно последовательно очистить только строки или только столбцы: var i, j: Integer; Казалось бы, можно поступить и по-другому, просто обнулить количество строк или столбцов! Однако так делать неправильно, так как при их последующем добавлении может оказаться, что каждая ячейка содержит прежние данные. А в Delphi4 даже при уменьшении количества строк или столбцов содержавшиеся в них данные вообще не пропадали, а так и повисали в воздухе! Так что так можно поступать только если в добавляемых ячейках сразу будет новое непустое содержимое. Компонент StringGrid умеет не хранить в своих ячейках не только текстовую информацию, но и графику. Графические возможности StringGrid определяются наличием у таблицы свойства Canvas - холста, на котором можно воспроизводить любую графику стандартными методами Delphi. Кроме того, компонент StringGrid имеет дополнительные методы, помогающие выводу графики в ячейки компонента. Графическими методами в таблице StringGrid можно, например, выводить текст в ячейке не только в одну, но и в несколько строк, произвольно раскрашивать ячейки, размещать рисунки и т.д. Работа с графическими свойствами компонента StringGrid происходит в обработчике OnDrawCell. По событию OnDrawCell происходит перерисовка таблицы, и следовательно, код в обработчике этого события будет управлять выводом на холст таблицы необходимой графики. Переменные этого обработчика помогут определить и прямоугольник, в котором будет происходить вывод графики: procedure TForm1.StringGrid1DrawCell(Sender: TObject; ACol, ARow: Integer; Для начала давайте выведем в ячейку (1, 1) компонента StringbGrid какой-нибудь рисунок. Вывести рисунок в ячейку компонента StringGrid проще всего, предварительно загрузив его в компонент Image: Image1.Picture.LoadFromFile('Имя_файла'); Загрузить рисунок в компонент Image можно, конечно, уже на этапе проектирования, в Инспекторе Объектов, вызвав графический редактор нажатием кнопочки в свойстве Picture. Затем нужно определить размеры загруженного рисунка: W:=Image1.Picture.Width; Далее, готовим ячейку под размещение рисунка. Для этого нужно задать её размеры кратными размерам рисунка. Например, сделаем размеры ячейки в 10 раз меньше размеров рисунка: StringGrid1.ColWidths[1]:=Round(W/10); Все эти манипуляции делаем предварительно, в обработчике OnCreate Формы, например. Ну и, наконец, в обработчике OnDrawCell выводим рисунок: procedure TForm1.StringGrid1DrawCell(Sender: TObject; ACol, ARow: Integer; Таким образом, при перерисовке таблица просматривает все ячейки и, встретив комбинацию ACol=1 и ARow=1, выводит в эту ячейку рисунок. Таким же способом можно и раскрасить заданные по любому условию ячейки в нужные цвета. Например, раскрасим ячейки с положительными числами в зелёный цвет, с отрицательными - в красный, с равными нулю в синий: procedure TForm1.StringGrid1DrawCell(Sender: TObject; ACol, ARow: Integer; Осталось рассмотреть возможности компонента StringGrid по выводу текста в ячейку таблицы в несколько строк. Если строки для вывода уже подготовлены, достаточно просто выводить строки со сдвигом по вертикали на высоту строки. Высота ячейки таблицы должна позволять вывод нескольких строк текста. Например, заголовок первого столбца: //В обработчике OnCreate Формы подготавливаем высоту строки: Разумеется, вывод лучше делать в цикле, заголовки столбцов записать в массив, ну и добавить возможность центрирования заголовка в строке. 17. Процедуры работы с памятью. Приведите примеры.
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Последнее изменение этой страницы: 2016-04-08; просмотров: 348; Нарушение авторского права страницы; Мы поможем в написании вашей работы! infopedia.su Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав. Обратная связь - 3.147.205.114 (0.01 с.) |