|
|||
5 Списки строк. Обработка исключительных ситуаций5 Списки строк. Обработка исключительных ситуаций 5. 1. Класс TStrings Очень часто при создании приложений необходимо отображать на экране не одну строку, а несколько. В Delphi для этого используются такие компоненты, как TComboBox, TLdstBox, TRichEdit, TNotebook, TTabSet, THeader и другие. Каждый из этих компонентов содержит свойство, принадлежащее типу TStrings. TStrings является абстрактным классом и предназначен для работы с наборами строк. Набор строк технически реализуется в виде массива указателей. С помощью свойств и методов данного класса можно добавлять и удалять строки, сортировать строки, считывать и записывать строки в файл или поток и т. д. Кроме того, элементами набора могут быть пары строка-объект, в которых строка является собственно строкой символов, а объектом может быть объект любого класса Delphi (в том числе и потомок от TStrings). Эта особенность позволяет сохранять в TStrings объекты с текстовыми примечаниями, сортировать объекты, отыскивать нужный объект по его описанию, создавать многомерные наборы строк и т. д. Свойства класса TStrings Свойство Capacity определяет количество строк, которое может храниться в наборе, а абстрактное свойство Count содержит текущее количество элементов. Если при добавлении очередного элемента Capacity окажется меньше Count, происходит автоматическое расширение массива. При этом в динамической памяти резервируется место для размещения Capacity+16 указателей, в новый массив переписывается содержимое старого массива, после чего старый массив уничтожается. Если вам известно количество элементов в создаваемом наборе строк, имеет смысл заранее нужным образом установить свойство Capacity, чтобы сократить непроизводительные расходы на многократные расширения массива указателей. Свойство CommaText служит для задания или получения всего набора строк в формате SDF (системный формат данных, который задает текст в виде единой строки с кавычками, запятыми и пробелами). Правила формата SDF: строки разделяются запятыми или пробелами (можно также заключить строки в двойные кавычки); если строка содержит двойные кавычки, то они удваиваются; две идущие подряд запятые обозначают пустую строку; все запятые и пробелы, не заключенные в двойные кавычки, считаются разделителями строк. Например, свойство CommaText имеет значение " Стро, ка1", " Стр" " ока 2",, Строка 3, Строка4 то набор состоит из строк: Строка1 Строка 2 Строка 3 Строка4 Следующие два свойства используются при представлении строк в формате Name=Value (имя = значение). Свойство Names содержит набор названий строк, a Values — набор соответствующих значений. Например, если i-я строка имеет вид Color=clGreen (обратите внимание, что ни до, ни после символа «=» не должно быть пробелов), то Names[i]: = f Color'; Values[i]: ='ClGreen'. Элементами набора строк могут быть пары строка—объект. Свойство Objects открывает доступ к объекту, связанному со строкой с номером Index. Нумерация строк начинается с нуля. Абстрактное свойство Strings используется для того, чтобы получить доступ к строке с номером Index. Для объектов класса TStrings свойство Strings является свойством по умолчанию, т. е. для доступа к конкретной строке необязательно использовать свойство Strings. Например, следующие операторы выполняют одно и то же действие: var MyStrings: TStrings; MyStrings. Strings [0]: = 'Это первая строка'; MyStrings [0]: = 'Это первая строка1; Свойство Text содержит набор строк объекта в виде одной длинной строки с символами возврата каретки и перехода на новую строку (стандартный признак разделения EOLN = #13#10). Методы класса TStrings function Add (const добавляет строку в набор данных и S: string): integer; возвращает ее индекс; virtual; function AddObj ect добавляет пару строка-объект в набор (const S: string; данных, возвращает индекс новой AObject: TObject): пары строка-объект; Integer; virtual; procedure добавляет к текущему набору новый AddStrings (Strings: набор строк; TStrings); virtual procedure Append добавляет строку в набор данных, но (const S: string); не возвращает индекс новой строки; procedure Assign уничтожает прежний набор строк и (Source: TPersistent); загружает из Source новый набор, override; Если строки в новом наборе связаны с объектами, то объекты также будут загружены; procedure Clear; очищает набор данных и освобождает virtual; abstract; связанную с ним память; procedure Delete уничтожает элемент набора с (index: Integer); индексом Index и освобождает virtual; abstract; связанную с ним память. Нумерация строк начинается с нуля; destructor Destroy; уничтожает объект класса override; TStrings. Рекомендуется не вызывать данный метод в приложении, а вместо него использовать метод Free; function Equals сравнивает построчно текущий (Strings: TStrings): набор данных С набором Strings и Boolean; возвращает True, если наборы идентичны; procedure Exchange меняет местами строки с индексами (Indexl, Index2: Indexl иIndex2; Integer); virtual; function GetText: помещает значение свойства Text в PChar; virtual; динамически создаваемый буфер;
Поместите компонент TabSet (список закладок) со страницы Win3. 1 под компонентом NoteBookl. Сделайте эти компоненты одинаковыми по ширине (рис. 5. 1. 3). Положите на каждую страницу компонента NoteBookl компонент ListBox (окно списка) для размещения записей на каждый месяц. Для этого выполните такую последовательность действий. Установите свойство ActivePage (активная страница) компонента NoteBook в значение, равное 'Январь*. Щелкните на выбранной странице объекта NoteBookl. В палитре компонентов на странице Standard выберите компонент ListBox и поместите (щелкните) в компонент NoteBookl. Свойство Align компонета ListBoxl установите в AlClient. Скопируйте компонент ListBoxl в буфер обмена (щелкните на объекте ListBoxl и выполните команду Edit/Copy). На вторую страницу блокнота поместите компонент Listbox2. Установите свойство ActivePage (активная страница) компонента NoteBookl в значение, равное 'Февраль'. Щелкните на компоненте Notebook 1 (для активизации этой страницы блокнота). Поместите копию компонента ListBoxl на страницу блокнота, выполнив команду Edit/Paste. Повторите эту операцию для оставшихся 10 страниц блокнота. Итак, сейчас для каждого месяца года существует свой компонент ListBox: для января — ListBoxl, для февраля — ListBox2 и т. д. В правую часть формы поместите компонент Panel (страница Standard палитры компонентов), на него положите один компонент Label, один компонент Edit и три компонента Button (рис. 5. 1. 3). Установите свойства компонентов следующим образом: Поместите еще 2 компонента Button в правой нижней части формы и измените свойства следующим образом: Итак, визуальное проектирование главной формы приложения завершено. Эксперимент. Сохраните проект. Убедитесь, что после запуска приложения форма ничем не отличается от режима проектирования. ♦ 2-й этап — создание программного кода Во-первых, необходимо создать закладки в TabSetl и синхронизировать их со страницами блокнота. Для этого используется свойство Tabs компонента TabSet, предоставляющее список имен закладок. В нашем примере список закладок соответствует списку страниц блокнота (Pages). Создайте следующий обработчик события: Procedure TNoteBookF. FormCreate(Sender: TObject); begin TabSetl. Tabs: =NoteBookl. Pages; {копируем содержимое свойства Pages компонента NoteBook в свойство Tabs компонента TabSet, т. е. создаем закладки в TabSet} TabSetl. TabIndex: =NoteBookl. Pagelndex; {В соответствии с тем, какая страница блокнота активна во время проектирования (свойство ActivePage), активной будет закладка с тем же именем (номером)} end; Эксперимент. Сохраните и запустите проект. Убедитесь в том, что закладки на форме получили названия, соответствующие страницам блокнота. Используя свойства UnSelectedColor, SelectedColor, Backgro-undColor, DitherBackground, StartMargin, EndMargin компонента TabSetl, измените внешний вид закладок. ♦ Создайте обработчик события OnClick для кнопки 'Добавить'. После щелчка на кнопке содержимое окна редактирования (RecordEdt) будет добавляться в список на странице блокнота. Для операций со строками у компонента ListBox имеется свойство Items, принадлежащее классу TStrings. Чтобы добавить строку в список, используется метод Add этого класса (см. таблицу методов класса TStrings п. 5. 1. 1). Обработчик события будет выглядеть следующим образом: 1-й способ procedure TNoteBookF. AddBtnClick{Sender: TObject); begin if RecordEdt. Text < > ' ' then begin case NoteBookl. Pagelndex of {Для того чтобы поместить запись в список на страницу блокнота, выбираем компонент ListBox по номеру страницы блокнота} 0: ListBoxl. Items. Add(RecordEdt. Text) 1: ListBox2. Items. Add(RecordEdt. Text) 2: ListBox3. Items. Add(RecordEdt. Text) 3: ListBox4. Items. Add(RecordEdt. Text) : ListBox5. Items. Add(RecordEdt. Text) : ListBox6. Items. Add(RecordEdt. Text) : ListBox7. Iterns. Add(RecordEdt. Text) : ListBox8. Items. Add(RecordEdt. Text) 8: ListBox9. Items. Add{RecordEdt. Text); : ListBoxlO. Items. Add(RecordEdt. Text); : ListBoxll. Items. Add(RecordEdt. Text); : ListBoxl2. Items. Add(RecordEdt. Text); end; RecordEdt. Text: =' '; {введенный текст затираем} end; end; Процедура получилась довольно громоздкой, ее можно описать по-другому. 2-й способ В Object Pascal определена функция: function FindComponent(const AName: string): TComponent; которая возвращает ссылку на компонент, имя которого задано параметром функции AName. Воспользуемся этой функцией в коде обработчика события OnClick кнопки 'Добавить': procedure TNoteBookF. AddBtnClick(Sender: TObject); var TempComponent: TListBox; {введем вспомогательную переменную} begin TempComponent: =TListBox{FindComponent('ListBox'+ IntToStr(Notebookl. Pagelndex+l))); {TListBox(< KOMnoHeHT> ) используется для преобразования к типу TListBox} if RecordEdt. Texto' ' then TempComponent. Items. Add(RecordEdt. Text); RecordEdt. Text: =''; end; Эксперимент. Сохраните и запустите проект. Попробуйте добавить строки на разные страницы блокнота. Объясните, почему все строки у вас записываются только на страницу, которая была открыта при запуске приложения. ♦ Строки записываются на одну страницу блокнота потому, что закладки Tabsetl не синхронизированы со страницами NoteBookl, т. е. при выборе закладки соответствующая страница блокнота не активизируется. Чтобы устранить этот недостаток, создайте обработчик события OnClick закладок: procedure TNoteBookFl. TabSetlClick{Sender: TObject); begin NoteBookl. Pagelndex: =TabSetl. Tablndex; {страница блокнота и страница набора закладок должны совпадать} end; Эксперимент. Сохраните проект. Проверьте правильность работы приложения, т. е внесение записей на страницы блокнота. ♦
Задания для самостоятельного выполнения 1. Напишите обработчик события нажатия кнопки 'Изменить': выделенная в списке страницы блокнота строка должна быть заменена содержимым окна редактирования. 2. Напишите обработчик события нажатия кнопки 'Удалить': выделенная в списке страницы блокнота строка должна быть удалена. 3. Напишите обработчик события нажатия кнопки 'Очистить': содержимое всего блокнота удаляется. 4. Модифицируйте программу следующим образом: при выборе записи на странице блокнота соответствующая запись отображается в окне редактирования; строка следующая (предыдущая) за удаленной становится выделенной и отображается в окне редактирования; добавление записи из окна редактирования происходит при нажатии клавиши ввода.
|
|||
|