Система тестирования. Часть 4

В предыдущей части цикла статей, посвященного написанию системы тестирования на Delphi, было начато создание программы для управления тестом.

Напомню внешний вид программы:

 

Ранее, мы разобрались с загрузкой документа, и написали обработчики события для кнопок «Открыть». Сейчас начнем работать с другими кнопками по порядку.

Создание нового документа

Кнопка в панели инструментов (NewToolButton) и пункт главного меню (New). При клике должен создаваться пустой документ, то есть, нет ни одного вопроса, пустое название теста и т.д.  Введем для этого новую процедуру CreateNew, опишем ее в секции private формы

  1. procedure TMainForm.CreateNew;
  2. begin
  3.   Data.LoadEmpty;
  4.   LoadData;
  5.   LoadQuestion( 0 );
  6. end;

Как видно, здесь загружается пустая модель данных. Теперь эту процедуру можно вызвать в обработчиках события клика по кнопкам «Создать».

  1. procedure TMainForm.NewClick(Sender: TObject);
  2. begin
  3.   CreateNew;
  4. end;
  5.  
  6. procedure TMainForm.NewToolButtonClick(Sender: TObject);
  7. begin
  8.   CreateNew;
  9. end;

Сохранение

Для начала, введем в класс формы закрытое поле Changed, типа boolean. Оно будет определять, изменились ли данные в процессе работы с программой. То есть, если мы добавим какой-нибудь вопрос, вариант ответа, отредактируем что-нибудь, то это поле станет true.

Оно введено для того, что бы при закрытии формы, программа спрашивала о сохранении сделанных изменений.

В событии onCreate формы сделаем это поле false, так как при создание формы, мы бы явно ничего не смогли изменить в тесте.

Теперь можно перейти к сохранению.

Создадим private процедуру SaveTest, они будет принимать один необязательный параметр fileName – имя файла, в который нужно сохранить текущий тест.

Это процедура собственно и выполняет само сохранение, используя метод Save из класса TStData.

  1. procedure TMainForm.SaveTest(fileName: string = '');
  2. begin
  3.   // Если введено какое-либо название теста
  4.   if TestNameEdit.Text <> '' then
  5.     begin
  6.       // Если имя файла не передано, используем строе
  7.       if fileName <> '' then
  8.         Data.FileName := fileName;
  9.      
  10.       // Сохраняем название теста
  11.       Data.StTest.Text := TestNameEdit.Text;
  12.       // Если ввели количество отображаемых вопросов
  13.       // Запоминаем их, в противном случае - 0
  14.       if (QCountCheckBox.Checked) and (QCountEdit.Text <> '') then
  15.         Data.StTest.QCount := StrToInt( QCountEdit.Text )
  16.       else
  17.         Data.StTest.QCount := 0;
  18.  
  19.       Data.Save; // Сохраняем изменения
  20.       StatusBar.Panels[0].Text := 'Сохранение прошло успешно';
  21.       // Поскольку уже все сохранено, то можно считать что
  22.       // данные пока не изменены
  23.       Changed := false;
  24.     end
  25.   else
  26.     StatusBar.Panels[0].Text := 'Введите название теста';
  27. end;

Теперь добавим еще один метод SaveTestSimple, его смысл в том, что бы просто сохранить документ в тот файл, из которого, он, собственно уже и открыт. То есть обычное сохранение. Но проблема в том, что если мы работаем с тестом открытым не из файла, а просто созданным прямо в программе, то ни какого файла нет, и, следовательно, нам нужно показать диалог «Сохранить как…».

  1. procedure TMainForm.SaveTestSimple;
  2. begin
  3.   // Если какой-либо файл есть
  4.   // Сохраняем в него
  5.   if Data.FileName <> '' then
  6.     SaveTest
  7.   else
  8.     begin
  9.       // В противном случае вызываем диалог
  10.       if SaveDialog.Execute then
  11.         SaveTest( SaveDialog.FileName );
  12.     end;
  13. end;

Теперь, когда основные методы сохранения написаны, можно перейти и к обработчикам событий клика по кнопкам «Сохранить» и «Сохранить как…».

  1. procedure TMainForm.SaveAsClick(Sender: TObject);
  2. begin
  3.   if SaveDialog.Execute then
  4.     SaveTest( SaveDialog.FileName );
  5. end;
  6.  
  7. procedure TMainForm.SaveToolButtonClick(Sender: TObject);
  8. begin
  9.   SaveTestSimple;
  10. end;
  11.  
  12. procedure TMainForm.SaveClick(Sender: TObject);
  13. begin
  14.   SaveTestSimple;
  15. end;

Добавление вопроса

Добавление вопроса реализуем следующий образом: при клике на кнопку «Добавить» показывается модальное окно, куда пользователь вводить текст нового вопроса, и при клике на кнопку «Ок» вопрос добавляется.

Внешний вид модального окна:

 

Создадим в Delphi новую форму (скачать dfm), назовем ее QCreateUnit.

Единственное что нам нужно, это написать обработчик события при клике на кнопку «Ок». Тут все просто. Создается новый вопрос, его текст и «активность» берутся из компонентов на форме, проверяется, не пустой ли текст, и потом, используя метод AppendQuestion, для объекта Data добавляется новый вопрос.

  1. procedure TQCreateForm.OkButtonClick(Sender: TObject);
  2. var
  3.   newQuestion: TStQuestion;
  4.   Data: TStData;
  5. begin
  6.   newQuestion := TStQuestion.Create;
  7.   if QTextMemo.Text <> '' then
  8.     begin
  9.       newQuestion.Text := QTextMemo.Text;
  10.       newQuestion.Active := QActiveCheckBox.Checked;
  11.       Data := TStData.GetInstance;
  12.       Data.AppendQuestion( newQuestion );
  13.     end;
  14. end;

На этом с окном добавления вопроса можно закончить, вернемся обратно к главной форме. Напишем обработчик события при клике на кнопку «Добавить…» панели инструментов.

Здесь мы показываем это модальное окно, и если был клик по кнопке «Ок», то вновь показываем все вопросы, и так же выделяем только что добавленный. И поскольку данные изменились, соответственно переменная Changed тоже стала true.

  1. procedure TMainForm.AddToolButtonClick(Sender: TObject);
  2. var
  3.   CreateForm: TQCreateForm;
  4. begin
  5.   CreateForm := TQCreateForm.Create( self );
  6.   if CreateForm.ShowModal = mrOk then
  7.     begin
  8.       Changed := true;    
  9.       LoadData;
  10.       QListBox.ItemIndex := QListBox.Count - 1;
  11.       LoadQuestion( QListBox.Count - 1 );
  12.     end;
  13. end;

Удаление вопроса

Удалять будем вопрос, выбранный в данный момент (свойство SelectQuestion). Введем метод DeleteSelectQuestion.

  1. procedure TMainForm.DeleteSelectQuestion;
  2. begin
  3.   Changed := true;
  4.   Data.DeleteQuestion( SelectQuestion );
  5.   FSelectQuestion := nil;
  6.   LoadData;
  7.  
  8.   LoadQuestion( 0 );
  9. end;

Тут просто идет удаления вопроса, и выделение первого вопроса.

Напишем обработчики событий клика для кнопок «Удалить» (RemoveToolButton) на панели инструментов и для метки тоже «Удалить» :) (QDeleteLabel) на панели «Редактирование вопроса»

  1. procedure TMainForm.QDeleteLabelClick(Sender: TObject);
  2. begin
  3.   if SelectQuestion <> nil then
  4.     if MessageBox(handle, 'Вы действительно хотите удалить этот вопрос?' + #13#10,
  5.       'Удаление вопроса', mb_YesNo) = mrYes then
  6.       DeleteSelectQuestion;
  7. end;
  8.  
  9. procedure TMainForm.RemoveToolButtonClick(Sender: TObject);
  10. begin
  11.   if SelectQuestion <> nil then
  12.     if MessageBox(handle, 'Вы действительно хотите удалить этот вопрос?' + #13#10,
  13.       'Удаление вопроса', mb_YesNoCancel) = mrYes then
  14.       DeleteSelectQuestion;
  15. end;

Проверяется, выбран ли в данный момент какой-либо вопрос, и если выбран, запрашивается подтверждение на его удаление.

Список вопросов (QListBox)

Единственное, что нужно от ListBox'a, куда выводятся вопросы, это что бы при клике на вопрос, он становился «выбранным» (свойство SelectQuestion). В обработчике события OnClick для QListBox напишем следующее:

LoadQuestion( QListBox.ItemIndex );

ItemIndex– это свойство ListBox'a, показывающее индекс выделенной строки.

Панель «Тест»

Перейдем к панелям справа. Сначала рассмотрим «Тест», здесь нужно только рассмотреть что будет при клике на Check Box. Если он выбрано, то задать количество отображаемых вопросов можно, в противном случае, поле Enabled.

  1. procedure TMainForm.QCountCheckBoxClick(Sender: TObject);
  2. begin
  3.   QCountEdit.Enabled := QCountCheckBox.Checked;
  4.   Changed := true;
  5. end;

Панель «Редактирование вопроса»

Для метки «Удалить» мы все написали, остались «Сохранить» и «Редактировать».

При клике на «Сохранить» должны сохраниться все изменения выбранного вопроса, сделанные на этой панели.

  1. procedure TMainForm.QSaveLabelClick(Sender: TObject);
  2. begin
  3.   if (SelectQuestion <> nil) and (QTextMemo.Text <> '') then
  4.     begin
  5.       SelectQuestion.Text := QTextMemo.Text;
  6.       SelectQuestion.Active := QActiveCheckBox.Checked;
  7.       Changed := true;
  8.       LoadData;
  9.     end;
  10.   end;

Внесем некоторые изменения в обработчик события OnCreate формы. Поскольку нам нужно что бы файл теста можно было открыть это программой, следовательно нужно при запуске программы, проверить переданы ли какие параметры командной строки, если переданы, то скорее всего это имя файла, который нужно открыть.

В Delphi есть две полезные функции для этого. ParamCount – возвращает количество параметров командной строки, а ParamStr – возвращет строку параметра под заданным номером.

  1. procedure TMainForm.FormCreate(Sender: TObject);
  2. begin
  3.   Data := TStData.GetInstance;
  4.   FSelectQuestion := nil;
  5.   Changed := false;
  6.   if ParamCount > 0 then Load(ParamStr(1));
  7. end;

На этом четвертую часть цикла статей можно завершить. Далее мы рассмотрим управление вариантами ответа и допишем программу составления теста.

delphi, тест

Комментарии (0)

Добавить комментарий

  • Допустимые html-теги:
    <b> </b> - жирный шрифт
    <em> </em> - наклонный
    <s> </s> - зачеркнутый
    <pre> </pre> - сохранение отступов (печать кода)
    [?]
Введите текст с картинки