Система тестирования. Часть 3
В предыдущей части цикла статей мы разобрали работу с данными из XML файла. Теперь уже можно приступить к написанию теста. Начнем с его админской части. Чуть более подробно распишем требования к системе администрирования, сформированные ранее:
- Возможность просмотра списка всех вопросов
- Добавление и удаление вопроса
- Редактирование текста вопроса
- Возможность изменять название теста и количество используемых вопросов
- Вопрос можно пометить как неактивный
- Для каждого вопроса можно просмотреть список вариантов ответа
- Добавление, удаление и редактирование вариантов ответа
- Вариантов ответа может быть любое количество, и верных из них тоже может быть хоть сколько
- Сохранение и загрузка XML файла
- Возможность работать без файла, потом все изменения просто сохранить
- Имя файла можно передать как параметр командной строки, и программа должна его открыть
Программа будет состоять из двух основных частей: управление вопросами и управление вариантами ответа для конкретного вопроса. Рассмотрим сначала управление вопросами и начнем с проектирования интерфейса.
Интерфейс приложения
Согласно требованиям от интерфейса нам нужно:
- Просмотр списка вопросов
- Кнопки для удаления, добавления и редактирования вопроса
- Область просмотра, куда будет выводиться текст вопроса, при редактировании
- Текстовое поле для названия теста и количества отображаемых вопросов
- Кнопки для открытия и сохранения файла
- Кнопка для создания пустого файла в памяти
- Check Box для обозначения активности вопроса
Я предлагаю следующий вариант:
Скачать dfm формы.
Список вопросов выводится в компонент QListBox типа TListBox. Управление настройками теста и редактирование текста вопроса вынесены в компоненты типа TCategoryPanelGroup (сворачивающиеся панельки).
Рассмотрим каждый компонент интерфейса по порядку.
ToolBar. Панель инструментов
Кнопка “создать”( NewToolButton: TToolButton)
В памяти создается XMLфайл нужной нам структуры, но пока без основных данных. В дальнейшем его можно будет сохранить на диск. Если до этого уже был открыт какой-то файл, он закрывается без сохранения.
Кнопка “открыть”( OpenToolButton: TToolButton)
Показывает диалог выбора файла, и если файл удалось открыть, показывается список вопросов. В противном случае в Status Bar'e выводится сообщение об ошибке открытия файла.
Кнопка “сохранить”( SaveToolButton: TToolButton)
Если файла до этого уже был открыт, то просто выполняет сохранения. Если же идет работа с только что созданным в памяти файлом, то открывает диалог «Сохранить как…»
Кнопка “добавить”( AddToolButton: TToolButton)
Добавление нового вопроса. Открывает диалог, в который можно ввести текст добавляемого вопроса и обозначить его активность.
Кнопка “редактировать”( EditToolButton: TToolButton)
Открывает, собственно, вторую часть программы, где идет управление вариантами ответа для вопроса, выбранного в данный момент в ListBox'e.
Кнопка “удалить”( RemoveToolButton: TToolButton)
Удаляет выбранный вопрос, при это запрашивает подтверждение.
MainMenu. Главное меню
В общем-то, компоненты главного меню выполняют ту же саму функцию, что и кнопки на панели инструментов.
Список вопросов
Как уже было сказано ранее, вопросы выводятся в компонент QListBox типа ListBox. Он настроен таким образом, что одновременно может быть выбран только один вопрос.
Панели управления, расположенные справа (EditPanelGroup: TCategoryPanelGroup)
Управление тестом (EditTestPanel: TCategoryPanel)
Текущее название теста выводится в компонент TestNameEdit типа TEdit. Если QCountCheckBox (TCheckBox), активный, то тогда можно задать количество отображаемых вопросов в поле QCountEdit (TEdit).
Редактирование вопроса (EditQuestionPanel: TCategoryPanel)
Возможность управлять выбранным вопросом.
Текст вопроса выводится в компонент QTextMemo (TMemo), в котором его можно редактировать. QActiveCheckBox (TCheckBox) позволяет задать «активность» вопроса.
Метка «Сохранить» (QSaveLabel: TLabel) позволяет сохранить сделанные изменения для вопроса (не в файл!).
Метки «Удалить» (QDeleteLabel: TLabel) и «Редактировать» (QEditLabel: TLabel) делают тоже самое, что и соответствующие компоненты панели инструментов.
Диалоги
Необходимо два диалога:
- OpenDialog: TOpenDialog – для открытия файла
- SaveDialog: TSaveDialog– для сохранения
С интерфейсом на этом можно закончить. Перейдем к загрузке данных из файла.
Получение вопросов из файла
Добавим в private формы следующие методы:
- TMainForm = class(TForm)
- ...
- private
- procedure Load( fileName: string );
- procedure LoadData;
- procedure LoadHead;
- end;
LoadHead – записывает данные из файла в компоненты управления тестом. То есть получает название и количество вопросов в тесте.
- LoadData – заносит вопросы из файла в список QListBox
- Load – общая загрузка файла.
Так же нам необходимо поле Data типа TStData. Что мы могли пользоваться созданным ранее набором методов по работе с файлом.
- TMainForm = class(TForm)
- ...
- public
- Data: TStData;
- end;
Для начала в обработчике события onCreate формы, нужно создать сам объект Data:
- procedure TMainForm.FormCreate(Sender: TObject);
- begin
- Data := TStData.GetInstance;
- end;
Теперь уже можно перейти к методам загрузки данных.
Метод Load
В качестве параметра получает имя файла с данными. Сначала, используя объект Data загружает его в память, далее вызывает методы LoadHeadи LoadData. Исключения обрабатываются.
- procedure TMainForm.Load( fileName: string );
- begin
- try
- Data.Load( fileName );
- LoadData;
- LoadHead;
- StatusBar.Panels[0].Text := 'Документ загружен успешно';
- except
- on EDOMParseError do
- StatusBar.Panels[0].Text := 'Неверный формат документа';
- else
- StatusBar.Panels[0].Text := 'Неверная структура файла';
- end;
- end;
Метод LoadHead
Название теста загружается в поле TestNameEdit. Потом проверяется, если количество вопросов больше нуля, то QCountCheckBox становится активным, и это количество вопросов заносится в поле QCountEdit. В противном случае переключатель не выбран и поле доступно только для чтения.
- procedure TMainForm.LoadHead;
- begin
- TestNameEdit.Text := Data.StTest.Text;
- if Data.StTest.QCount > 0 then
- begin
- QCountCheckBox.Checked := true;
- QCountEdit.Text := IntToStr( Data.StTest.QCount );
- QCountEdit.Enabled := true;
- end
- else
- begin
- QCountCheckBox.Checked := false;
- QCountEdit.Text := '';
- QCountEdit.Enabled := false;
- end;
- end;
Метод LoadData
Выводит список вопросов в компонент QListBox.
- procedure TMainForm.LoadData;
- var
- i: integer;
- Question: TStQuestion;
- begin
- QListBox.Items.Clear;
- for i := 0 to Data.StQuestionList.Count - 1 do
- begin
- Question := TStQuestion( Data.StQuestionList.Items[i] );
- QListBox.Items.Add( Question.Text );
- end;
- end;
Теперь, когда данные из файла мы уже может увидеть на форме, то onClick обработчики событий кнопок «открыть» панели инструментов и главного меню можно прописать следующее:
- if OpenDialog.Execute then Load(OpenDialog.FileName);
Скачав файл теста здесь, вы уже можете проверить, как все работает.
В тексте выше не раз встречалась фраза «выбранный вопрос», то есть тот вопрос, который в данный момент выбран в ListBox'e. Для удобства сделаем этот вопрос свойством, при записи в который будет выполняться некоторый метод SetSelectQuestion:
- TMainForm = class(TForm)
- ...
- private
- FSelectQuestion: TStQuestion;
- ...
- public
- ...
- property SelectQuestion: TStQuestion read FSelectQuestion write
- SetSelectQuestion;
- end;
- //...
- procedure TMainForm.SetSelectQuestion(const Value: TStQuestion);
- begin
- QTextMemo.Text := Value.Text;
- QActiveCheckBox.Checked := Value.Active;
- FSelectQuestion := Value;
- end;
Как видно при выборе вопроса, его текст и записываются в компоненты QTextMemo и QActiveCheckBox.
Добавим еще один закрытый метод LoadQuestion. Он будет делать выбранным вопрос под заданным индексом. Как мы помним, вопросы в классе TStData хранятся в списке TObjectList, и соответственно вопрос можно получить, обратившись по индексу.
- TMainForm = class(TForm)
- ...
- private
- ...
- procedure LoadQuestion( index: integer );
- public
- ...
- end;
- procedure TMainForm.LoadQuestion( index: integer );
- begin
- // Если индекс вопроса, который нужно сделать выбранный, не отрицательный
- // и меньше общего количества вопросов
- if (index >= 0) and ( index < Data.StQuestionList.Count ) then
- SelectQuestion := TStQuestion( Data.StQuestionList.Items[index] )
- else // В противном случае
- begin
- QTextMemo.Text := '';
- QActiveCheckBox.Checked := true
- end;
- end;
Исправим метод Load, добавив в блок try следующую строчку:
- LoadQuestion( 0 );
Таким образом, каждый раз при открытии файла выбранным будет первый вопрос. Это сделано во избежание некоторых ошибок.
На этом третью часть цикла статей по написанию системы тестирования можно завершить.
delphi, тест

Комментарии (2)
а исходник этого можно?:))
Хм ,
все нашел)
Добавить комментарий