Page 2. Creating RadioButtons at Run-time

The application below shows a fully functioning quiz, albeit with only two questions. Note that the structure we set up on the stage works as we proposed, but the content (title text, question text, and answer choices) are created at run-time. That is, we did not put the questions and answers on the stage when authoring the problems.

In order to keep the code as simple as possible, the content in the example below does not come from an external file, but is specified with variables within the script given below. Our last step will be to replace this with xml loading as we have seen in other tutorials.

The code

The following classes must be imported, and in addition the library must contain the radio button class. If you add a radio button to the stage and then delete it, it will persist in the library.

import fl.controls.RadioButton;

import fl.controls.RadioButtonGroup;

For ease of positioning and maintenance, we create a "question holder" on which the question text and answer components will be placed.

var qHolder:MovieClip = new MovieClip();

qHolder.x = 30;

qHolder.y = 60;

addChild(qHolder);

The following variables control the size of question and answer box, including the font color and size for the questions. The information in this block of code will be loaded from an external xml file in the final version of this application in this tutorial.

var qHeight:Number = 50;

var qWidth:Number = 500;

var aHeight:Number = 30;

var aWidth:Number = qWidth;

var qSize:Number = 16;

var qColor:uint = 0x000000;

Set the title for this quiz.

txtTitle.text = "History Quiz";

// An array containing the two questions in this quiz:

var arrQuestion:Array = [ "What was the name of the Simon Stevin 1586 pamphlet that popularized decimals?", "What people wrote the collection of problems in the Rhind Papyrus?"];

// An array of two arrays, each containing answer choices:

var arrAnswers:Array = [["Liber Abbaci","Nine Chapters","The Tenth","Arithmetica","Principia"], ["Greeks", "Romans", "Indians", "Egyptians"]];

// An array containing the indices of the correct answers to the two questions:

var arrCorrect:Array = [2, 3];

// An array containing the indices of the user answers, initialized to 0:

var arrUserAnswers:Array = [0,0];

// A 0-1 array to signal that a question has the correct answer selected:

var arrDone:Array = [0,0];

We need a variable for the number of questions in this quiz, and declare a variable index that will serve as the number (literally the array index) for the current question.

var numExamples:int = arrQuestion.length;

var index:int = 0;

The array arrChoices will contain the radio buttons for the current question. In addition, we need to declare a variable for the group name: The selected radio button is a property of the group, so we need the group to have a name. Also, the group can listen for the CHANGE event, so we can use that to update the "user answer."

var arrChoices:Array = new Array();

var rbg:RadioButtonGroup = new RadioButtonGroup("answerGroup");

The setup function removes the old question & answers and places the current questions & answers in qHolder.

function setup():void {

var j:int;

// Since qHolder has no children other than questions and answers,

// we remove all of its children to clear the previous question.

while (qHolder.numChildren > 0) {

qHolder.removeChild(qHolder.getChildAt(0));

}

// Update problem counter and clear feedback for the new problem.

txtCounter.text = "Problem " + String(index+1) + " of " + String(numExamples) + ".";

txtFeedback.text = "";

/*

The format of the question is set inside of the setup function in case the user wants to add the ability to handle custom formatting for individual questions in the same problem set.

*/

var qFormat:TextFormat = new TextFormat('Arial',qSize,qColor);

// We build the text field according to specified parameters

// and add it as a child of qHolder.

var qField:TextField = new TextField();

qField.width = qWidth;

qField.height = qHeight;

qField.x = 0;

qField.y = 0;

qField.multiline = true;

qField.wordWrap = true;

qHolder.addChild(qField);

// Set the format and content of the textfield.

qField.defaultTextFormat = qFormat;

qField.text = String(index+1) + ". " + arrQuestion[index];

/*

Make the "check mark" mcCheck visible if this question has already been answered correctly.

*/

if (arrDone[index] == 1) {

mcCheck.visible = true;

}

else {

mcCheck.visible = false;

}

/*

Create an array to hold the radio buttons for the choices, and set up the radio buttons, adding each as a child of qHolder.

*/

arrChoices = new Array(arrAnswers[index].length);

for (j=0; j<arrAnswers[index].length; j++) {

arrChoices[j] = new RadioButton();

arrChoices[j].label = arrAnswers[index][j];

arrChoices[j].value = j;

arrChoices[j].width = qField.width;

arrChoices[j].x = qField.x + 10;

arrChoices[j].y = qField.y + qHeight + (aHeight+5)*j;

arrChoices[j].group = rbg;

qHolder.addChild(arrChoices[j]);

}

//Set the initial selection for the radio button group.

arrChoices[arrUserAnswers[index]].selected = true;

/*

Move the "CHECK" button btnCheck (already on the stage) to an appropriate spot below qHolder.

*/

btnCheck.x = qHolder.x;

btnCheck.y = qHolder.y + qHeight + arrAnswers[index].length*(aHeight + 5) + 10;

}

Changing the selected radio button will update the saved "user answer" array but not check the answer. The answer is only checked when the user clicks the "CHECK" button, btnCheck.

rbg.addEventListener(Event.CHANGE, updateAnswer);

function updateAnswer(evt:Event):void {

arrUserAnswers[index] = rbg.selectedData;

}

Clicking the btnCheck button checks the user answer and updates the arrDone array as well as makes the check mark (mcCheck) visible if and only if the answer is correct.

btnCheck.addEventListener(MouseEvent.CLICK, chkAnswer);

function chkAnswer(mevt:MouseEvent):void {

if (arrCorrect[index] == arrUserAnswers[index]) {

txtFeedback.text = "CORRECT!";

arrDone[index] = 1;

mcCheck.visible = true;

}
else {

txtFeedback.text = "NO, TRY AGAIN.";

arrDone[index] = 0;

mcCheck.visible = false;

}

}

The "next" and "previous" (btnNext and btnPrev) buttons simply step through the problems (referenced by the variable index) in a cycle.

btnNext.addEventListener(MouseEvent.CLICK, goNext);

function goNext(mevt:MouseEvent):void {

index++;

if (index > (numExamples - 1)) {

index = 0;

}

setup();

}

 

btnPrev.addEventListener(MouseEvent.CLICK, goPrev);

function goPrev(mevt:MouseEvent):void {

index--;

if (index < 0) {

index = numExamples - 1;

}

setup();

}

The "QUIT" button (btnDone) calls the finish function.

btnDone.addEventListener(MouseEvent.CLICK, donePressed);

function donePressed(mevt:MouseEvent):void {

finish();

}

We have previously created and linked the EndClip movie clip containing a dynamic text box that we can write results into. When the "QUIT" button is pressed, we create an instance of this clip and put the appropriate text in its textbox. In addition, we have this new clip (which completely covers the stage area) start listening for a mouse click so it can close itself when the user clicks.

function finish():void {

var stMessage:String;

var mcFinal:EndClip = new EndClip();

var score:Number = 0;

mcFinal.x = 5;

mcFinal.y = 5;

addChild(mcFinal);

// The score is the number that are currently answered correctly.

for (var i=0; i<numExamples; i++) {

score += arrDone[i];

}

stMessage = "You got " + String(score) + " of " + String(numExamples) + " problems correct. Click anywhere to go back ";

stMessage = stMessage + "and work on them some more. Problems without a check mark are not answered correctly.";

mcFinal.txtReport.text = stMessage;

mcFinal.addEventListener(MouseEvent.CLICK, closePanel);

}

When the mcFinal clip is clicked, the mcFinal clip is removed entirely.

function closePanel(mevt:MouseEvent):void {

var mcFinal:MovieClip = mevt.currentTarget as MovieClip;

mcFinal.removeEventListener(MouseEvent.CLICK, closePanel);

removeChild(mcFinal);

setup();

}

We must call the setup function so the first problem is presented on the screen when the user starts the application.

setup();

Download

Download the well-commented fla file for the application shown above.

Back to Intermediate Tutorials              Back to Flash and Math Home

The site www.flashandmath.com is maintained by Doug Ensley (doug@flashandmath.com) and Barbara Kaskosz (barbara@flashandmath.com).
It has been developed with partial funding from the National Science Foundation and the Mathematical Association of America.