Студопедия.Орг Главная | Случайная страница | Контакты | Мы поможем в написании вашей работы!  
 

Добавляю новый элемент в дерево вопросов with QuestionTreeView.Items.Add(nil, NewQuest.Name) do



begin
ImageIndex:=0;
Data:=NewQuest;

end; end;

В самом начале я очищаю элементы управления окна EditQuestionForm. Потом я отображаю это окно, и если пользователь ввёл название вопроса и нажал ОК, то нужно обработать введённую информацию. Для начала выделяется память под переменную NewQuest. Эта переменная объявлена как PQuestion, а это указатель на структуру ТQuestion. Как ты знаешь, любые указатели создаются пустыми и чтобы они на что-то указывали, им надо выделять память. Я выделяю память с помощью функции New. Этой функции нужно передать в качестве параметра подо что нужно выделять память. Я указываю наш указатель PQuestion, по которому функция определит, сколько памяти надо выделить. Результат выполнения функции – указатель на выделенную память, который я сохраняю в переменной NewQuest.

Если нужно уничтожить выделенную память, то мы должны вызвать процедуру Dispose и передать ей переменную, которую нужно уничтожить, например Dispose(NewQuest). Но мне не надо уничтожать эту переменную, потому что она потом будет использоваться и я её добавляю в список QuestionList типа TList.

После того, как я выделил память для структуры NewQuest, я заполняю её поля в зависимости от введённой пользователем информации. Как только всё заполнено, я добавляю структуру в список:

QuestionList.Add(NewQuest);

После этого происходит самое интересное. Я должен создать новый элемент в дереве вопросов. Для этого выполняется следующий код:

with QuestionTreeView.Items.Add(nil, NewQuest.Name) do begin ImageIndex:=0; Data:=NewQuest; end;

Давай разберём этот код по частям. В первой строке я добавляю в дерево новый элемент с помощью вызова QuestionTreeView.Items.Add. В качестве параметров методу Add нужно передать указатель на родительский элемент в дереве и текст элемента. В качестве родительского элемента я передаю nil потому что я буду создавать дерево без вложенных элементов. В качестве текста элемента я передаю текст вопроса.

Выполненный метод Add возвращает указатель на созданный элемент. И тут у меня стоит оператор with, который заставляет выполнять следующие действия с указанным объектом. Получается, что следующие действия между begin и end будут выполняться с созданным элементом дерева вопросов. А у меня тут выполняется два действия:

ImageIndex:=0 – индексу иконки присваивается значение 0. Я бросил на форму список картинок ImageList, загрузил туда несколько картинок и указал этот список в свойстве Images нашего дерева. В этом коде я назначаю элементу первую картинку из созданного списка.

Data:=NewQuest – Свойство Data элемента дерева – это такое же свойство, как Tag у всех компонентов. Оно так же не влияет на работу компонента и его элементов и может использоваться в наших собственных целях. Это свойство имеет значение указателя, и мы можем в него вносить любые указатели. Я указываю здесь указатель на структуру NewQuest, которая связана с созданным элементом.

Теперь создадим обработчик события OnChange для нашего дерева:

procedure TQuestionResultForm.QuestionTreeViewChange(Sender: TObject; Node: TTreeNode); var i:Integer;

begin // Очищаю список ResultView.Items.Clear;


// Если не выделен элемент, то выход
if Node=nil then exit;

// Запускаю цикл, по которому заполняются данные списка for i:=0 to PQuestion(node.Data).ResultCount-1 do with ResultView.Items.Add do

begin
Caption:=PQuestion(node.Data).ResiltText[i];
if PQuestion(node.Data).ResiltValue[i]=true then

begin
SubItems.Add('Да');
ImageIndex:=2;

end
else

begin
SubItems.Add('Нет');
ImageIndex:=1;

end; end; end;

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

В обработчик события нам передаётся параметр Node типа TTreeNode, который указывает на выделенный элемент. Второй строчкой кода я проверяю, если выделенный элемент равен nil (ничего не выбрано), то нужно выходить из процедуры.

Чтобы получить доступ к структуре PQuestion, в которой хранятся данные об ответах выделенного вопроса, мы должны обратиться к свойству Data выделенного элемента Node. Как ты помнишь, в это свойство мы поместили указатель на структуру PQuestion. Но программа не может знать какого типа этот указатель, поэтому мы должны явно указывать это - PQuestion(node.Data).

Далее, я запускаю цикл от 0 до количества вариантов ответов в данном вопросе PQuestion(node.Data).ResultCount минус 1. Внутри цикла я выполняю код ResultView.Items.Add, который создаёт очередной элемент списка. Здесь метод Add также возвращает указатель на созданный элемент, вместе с которым и будет выполняться дальнейший код (об этом говорит оператор with). А внутри кода я выполняю следующее:

1. 1. Заполняю заголовок элемента Caption.

2. 2. Если PQuestion(node.Data).ResiltValue[i] равно true, то есть ответ верный, то я добавляю дочерний элемент (текст этого элемента будет отображаться во второй колонке списка) SubItems.Add('Да') и присваиваю 2-й индекс иконки. Иначе текст дочернего элемента будет равен «Нет» и иконка будет иметь индекс единицы.

Таким образом, внутри цикла будет обработаны все варианты ответов, и все они будут добавлены в список. Попробуй сейчас запустить программу и создать пару вопросов с различными вариантами и посмотреть, как всё будет выглядеть. Моё окно программы ты можешь увидеть на рисунке 25.3.8.

Совсем забыл описать код, по которому мы будем отображать окно, показанное мной на рисунке 25.3.8. Для этого нам надо подкорректировать обработчик события OnClick для кнопки создания нового проекта теста:

procedure TTestEditorForm.NewButtonClick(Sender: TObject);

begin NewTestForm.ShowModal; if NewTestForm.ModalResult<>mrOK then exit;

if NewTestForm.TestTypeBox.ItemIndex=0 then

begin QuestionResultForm:=TQuestionResultForm.Create(Owner); QuestionResultForm.ProjectName:=NewTestForm.TestNameEdit.Text; QuestionResultForm.Caption:=QuestionResultForm.Caption+': '

+QuestionResultForm.ProjectName; end; end;

Здесь в первой строке я показываю окно создания нового проекта. Если пользователь выбрал первый тип теста «Вопрос -варианты ответа» (в моей книге он будет описан как единственный), то создаётся окно, в котором мы создаём вопросы. Потом я сохраняю имя выбранного проекта и изменяю заголовок окна.

Обработчики события кнопок «Редактировать» и «Удалить» вопросы я расписывать не буду, а только приведу их код с комментариями. Ты уже должен разобраться с этим кодом:

procedure TQuestionResultForm.EditButtonClick(Sender: TObject); var i:Integer;

begin // Здесь QuestionTreeView.Selected указывает на выделенный элемент // в дереве. Если он равен nil, то ничего не выделено, и нужно выйти if QuestionTreeView.Selected=nil then exit;

// Заполняю компонент QuestionEdit в окне редактирования вопросов
EditQuestionForm.QuestionEdit.Text:=PQuestion(QuestionTreeView.Selected.Data).Name;

// Очищаю список вариантов ответов в окне редактирования вопросов
EditQuestionForm.ResultListBox.Clear;
for i:=0 to PQuestion(QuestionTreeView.Selected.Data).ResultCount-1 do

begin
// Заполняю список вариантов ответов в окне редактирования вопросов
EditQuestionForm.ResultListBox.Items.Add(

PQuestion(QuestionTreeView.Selected.Data).ResiltText[i]);

// Если ответ верный, то ставлю галочку
if PQuestion(QuestionTreeView.Selected.Data).ResiltValue[i]=true then
EditQuestionForm.ResultListBox.Checked[i]:=true;
end;

// Отображаю окно редактирования вопроса
EditQuestionForm.ShowModal;
if EditQuestionForm.ModalResult<>mrOK then exit;

// Записываю информацию обратно в структуру PQuestion(QuestionTreeView.Selected.Data).Name:=EditQuestionForm.QuestionEdit.Text; PQuestion(QuestionTreeView.Selected.Data).ResultCount:=

EditQuestionForm.ResultListBox.Items.Count; for i:= 0 to PQuestion(QuestionTreeView.Selected.Data).ResultCount-1 do begin PQuestion(QuestionTreeView.Selected.Data).ResiltText[i]:= EditQuestionForm.ResultListBox.Items.Strings[i]; PQuestion(QuestionTreeView.Selected.Data).ResiltValue[i]:=

EditQuestionForm.ResultListBox.Checked[i];
end;

// Вызываю процедуру QuestionTreeViewChange, которая должна обновить // информацию в ResultView. Первый параметр нас не интересует, а второй // мы обязаны указать, потому что внутри процедуры QuestionTreeViewChange // мы используем его. Я указываю выделенный элемент. QuestionTreeViewChange(nil, QuestionTreeView.Selected);

end;

Единственное, что я здесь хочу отметить, так это то, что здесь я обращаюсь к структуре связанной с элементом через свойство Data выделенного элемента. Как я уже говорил, там храниться указатель на структуру. То же самое можно было бы делать, обращаясь через контейнер, просто в данном случае это будет не так удобно. Но всё же это возможно и на всякий случай я приведу пример, как можно обратиться к свойству Name:





Дата публикования: 2014-11-04; Прочитано: 456 | Нарушение авторского права страницы | Мы поможем в написании вашей работы!



studopedia.org - Студопедия.Орг - 2014-2024 год. Студопедия не является автором материалов, которые размещены. Но предоставляет возможность бесплатного использования (0.013 с)...