which method should i use to create a new keyboard using adobe flash - actionscript-3

I'm trying to create a new keyboard somehow, for educational purposes.
I've written this code using actionscript 3.I've created an input text field (named it t1) .when the user presses q button on keyboard(which has an ASCII aquals 81 ) I want the letter b to be printed out on the text field so i've written this code :
stage.addEventListener(KeyboardEvent.KEY_DOWN, pressing);
function pressing(event:KeyboardEvent):void
{
//trace(event.keyCode);
if(event.keyCode==81)
t1.replaceSelectedText("b");
}
the problem was that the method replaceSelectedText prints the tow letters on the screen(q&b) which method can i use instead?
Any help would be appreciated.

When using the replaceSelectedText method, you first need to select the text you want to replace. This can be done with the "setSelection" method. This from the adobe help website:
setSelection(beginIndex:int, endIndex:int):void
"Sets as selected the text designated by the index values of the first and last characters, which are specified with the beginIndex and endIndex parameters."
At the moment, since you don't have any text selected, it appears to just be adding the text "b" as it's replacing nothing. Therefore, you should try first selecting the "q".
Alternatively, you can just use a different method. from the adobe help website:
replaceText(beginIndex:int, endIndex:int, newText:String):void
"Replaces the range of characters that the beginIndex and endIndex parameters specify with the contents of the newText parameter."
This would cut out an extra line of code.
I haven't actually done this myself, so if that doesn't work, here's the link to the adobe help page for Text Fields: http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/flash/text/TextField.html

I think that to do what you are looking for ( replace a char when it's typed ), a KeyboardEvent.KEY_DOWN is not enough, because when that event is fired, the text is not yet changed, so any change that you did in its handler to your text field will not cancel the insertion of the current typed char. Also, using KeyboardEvent.KEY_UP ( in addition to KeyboardEvent.KEY_DOWN ) will not resolve the problem, because you can fire n times a KeyboardEvent.KEY_DOWN event with the KeyboardEvent.KEY_UP event fired once !
So, I think that the best event that can do the job is the Event.CHANGE event which is fired every time the text of your text field is changed, so you can do like this :
// is there a char to replace ?
var replace_char:Boolean = false;
// the position of the char that we want to replace
var char_position:int = -1;
var text_input:TextField = new TextField();
text_input.type = 'input';
text_input.border = true;
text_input.addEventListener(Event.CHANGE, onTextChange);
function onTextChange(e:Event):void {
if(replace_char && char_position >= 0){
text_input.replaceText(char_position, char_position + 1, 'b');
replace_char = false;
}
}
addChild(text_input);
stage.addEventListener(KeyboardEvent.KEY_DOWN, _onKeyDown);
function _onKeyDown(e:KeyboardEvent):void {
if(e.keyCode == 81) {
replace_char = true;
char_position = text_input.selectionBeginIndex;
}
}
EDIT :
To use a list of keys and their equivalents, you can use an object to stock your keys like this :
// list of all keys (chars) and their equivalents
var chars:Object = {
81: 'b', // q => b
83: 'v', // s => v
68: 'c' // d => c
// other chars
}
var char_to_replace:int = -1;
// other instructions
function onTextChange(e:Event):void {
if(replace_char && char_position >= 0 && char_to_replace >= 0){
// get the equivalent of the pressed key from chars object using : chars[key_pressed]
text_input.replaceText(char_position, char_position + 1, chars[char_to_replace]);
replace_char = false;
}
}
// other instructions
function _onKeyDown(e:KeyboardEvent):void {
if(chars[e.keyCode]) {
replace_char = true;
// save the last pressed key to get its equivalent, or save this last one directly, to replace it next
char_to_replace = e.keyCode;
char_position = text_input.selectionBeginIndex;
}
}
Hope that can help.

Related

AS3 event.target and var

I have an editable text field (c) in a movieClip, well 3 movielips like this actually named a1, a2 and a3. Movieclips are already on stage. The path to text field in each MC is mc.a1.c, mc.a2.c and mc.a3.c
The initial value for each textfield is set by XML which is also stored in variables with the same names and the movieclip(a1,a2,a3). If the user updates a textfield a CHANGE event listener triggers checkValue function. If the value is greater than my maxValue I want my function to return the text field to its original value and give the user an error message. So if textfield c in mc.a1.c is updated, I'm currently taking the name of its parent (a1) and then trying to reference the variable with the same name so that textfield c will be returned to the initial value held in var a1 (I'll only know which var to reference once a textfield update has been attempted.. hope that makes sense)
I've tried several things but always end up with the variable name, and not its value in the textfield. So, for now I've reverted to populating the field with 0 until I can find an answer.
example code:
aH.t1 is the predefined max value
function chngTh(event:Event):void{
var thR:String = String(event.target.parent.name.substring(0,1));
if (thR =="a"&&thN>int(aH.t1.text)){
event.target.text = 0; //I want the reference var a(x)and have its value in the text field
aH.errorMsg.text = "The number cannot be greater than 10 so the original value has been restored";
}
}
As you can probably tell my my code, I'm not a developer and I've already looked here in search of but can't seem to get grasp it...Is it me?
reference variable AS3
AS3: Using string as variable
Is what I'm trying to do achiveable in AS3?
Thanks to guidance from dene the solution looks like this:
function chngTh(event:Event):void{
var thR:String = String(event.target.parent.name.substring(0,1));
var thN:int = (event.target.text);
var thov:int = root[event.target.parent.name];
if (thR =="a"&&thN>int(aH.thrsh.t1.text)){
event.target.text = thov;
aH.errorMsg.text = hclbl[12];
}
}
Use event.target in the listener function to reference the text field that changed:
var maxValue = 5;
myTextField.addEventListener(Event.CHANGE, textListener);
function textListener(event:Event)
{
var tf = event.target as TextField;
var currentValue = parseFloat(tf.text);
if (currentValue > maxValue) {
tf.text = getOriginalValue(tf);
}
}
function getOriginalValue(tf:TextField) : Number
{
// Assuming the textfield's parent is named "a" + number (eg. a1, a2 etc.)
// Get the number of the parent by ignoring the character at index 0
var parentName = tf.parent.name;
var parentNumber = parentName.substring(1);
// Now you can use parentNumber to access the associated variable (a1, a2, etc)
// Assuming these variables are defined on the root (main timeline).
var originalValue = root["a" + parentNumber]
// If the variables are stored as Strings, this line is needed to convert it to a Number type
originalValue = parseFloat(originalValue)
return originalValue;
}

Create a list of Button in Cocos2dx

When I create a list of button and I addTouchEventListener for it, like below code
for (int i = 0; i < btmPlay.size(); i++ )
{
btmPlay.at(i)->addTouchEventListener([&](Ref *sender, ui::Widget::TouchEventType type){
if (type == ui::Widget::TouchEventType::ENDED)
{
CCLOG("%i", i);
}
});
}
when I touch to the first button, the result is 12 ( btmPlay.size() = 13).
What errors?
In your closure, you're capturing the variable i by reference, and that's why clicking any button will print the same value, in this case 12. If, instead, you capture the variable i by value (by replacing [&] with [=]) then each button will print a different value in the range 0-12.
Btw, capturing i by reference in your example is also wrong, because by the time the closure is invoked, the variable is already out of scope, and printing it is UB.

summing the numbers after appendText to a textField

as3 using appendText. I'm simply stringing out numbers like entering from a button press.
key2.addEventListener(MouseEvent.MOUSE_DOWN, thisButkey2);
function thisButkey2 (e:MouseEvent):void{
displayNums.appendText("2") ;
}
key3.addEventListener(MouseEvent.MOUSE_DOWN, thisButkey3);
function thisButkey3 (e:MouseEvent):void{
displayNums.appendText("3") ;
}
How do I total the string text into one number? I'd like to find out if it is > 100.
I solved it - It simply needed to be turned into a Number.
keyEnter.addEventListener(MouseEvent.MOUSE_DOWN, thisButEnter);
function thisButEnter (e:MouseEvent):void{
totalSum = Number(displayNums.text)
if ( totalSum > 100){
clearNums();
}
}
Here's a way to do this:
stage.addEventListener(KeyboardEvent.KEY_DOWN,processentry)
var entry:int;
var sum:int;
function processentry(e)
{
trace ("hello "+e.keyCode)
entry = e.keyCode - 48;
sum += entry;
trace(sum);
}
The first 'trace' simply makes clear what's happening when you press a key. We subtract 48 from the keyCode because the ASCII keyCode for '0' is '48' and the other digits' keyCodes go up sequentially. It should be easy for you to adapt this to your own case. Just let your textfield append the current 'entry'. You can put the 'sum' into another textfield or do something else with it.

Trying to remove all children, receiving error #1009

The idea with my setup is that I have an input text field and three separate buttons on stage. When you type something in the text field and press the input button, the text inside the field is added to an array.
When you press the display button the contents of the array are displayed on screen (each value of the array is displayed underneath the last value).
The final button is supposed to remove all the current values on the array, and clear all displayed values on screen. But I cannot get my code to work as intended, since I receive,
TypeError: Error #1009: Cannot access a property or method of a null object reference.
With this block of code:
import flash.text.TextField;
import flash.events.MouseEvent;
var myArray:Array = new Array ("");
var tf:TF;
btnInput.addEventListener(MouseEvent.CLICK, txtInput);
function txtInput(event:MouseEvent):void
{myArray.push(txtInput.text);}
btnDisplay.addEventListener(MouseEvent.CLICK, txtDisplay);
function txtDisplay(event:MouseEvent):void
{for (var i:int = 0; i < myArray.length; i++)
{var tf:TF = new TF();
tf.txt.text = myArray[i];
tf.y = 280 + (i * 25);
tf.x = 265;
addChild(tf);
tf.name="test";}
}
btnClear.addEventListener (MouseEvent.CLICK, txtClear);
function txtClear(event:Event){
myArray.splice(1);
if (tf.numChildren != 0){
removeChild(getChildByName("test"));}
}
Alternatively, when I add
var tf:TF = new TF;
It removes only one displayed value on screen. Also I might add, that "TF" is a movie clip in the library that contains a dynamic text field that's instance name is txt. Is the problem only with the last button, or should I change something else as well? I don't know how to make this work as I want it to. I'm pretty new to coding so any tips or help would be much appreciated. Thanks in advance!
In your condition if(tf.numChildren != 0) the tf object is null since you never created it. That's why you're getting the #1009 error.
On the other hand, in order to delete all items you should replace the if (tf.numChildren != 0) with while (tf.numChildren != 0).

How to keep element grayed out unless a conditional is met?

I'm in the process of designing a Flash application, and it requires either two or three pieces of data from the user. The third data element is only relevant if one of the other elements has changed from the default value.
In order to prevent the user from inputting information that would skew the calculations based on the input, how can I gray out the text input box if the default conditional is unchanged? I could embed a conditional to ignore the input from that particular box, but I know that some users will fill in all data fields regardless of on-screen instructions.
Just use the Event.CHANGE listener + handler to check the condition/state of elements. This event is fired every single time the user alters a component. For example, heres a text input doing this:
var tf:TextInput = new TextInput();
var someOtherObject:Button = new Button();
tf.x = 100;
tf.y = 100;
tf.width = 150;
stage.addChild(tf);
stage.addChild(someOtherObject);
tf.addEventListener(Event.CHANGE, onFormChanged);
private function onFormChanged(e:Event):void
{
switch(e.currentTarget){
case tf:
//Do your conditional checks here.
if(tf.text.toString().length < 10){
someOtherObject.enabled = false;
someOtherObject.text = "";
someOtherObject.maxChars = 0;
}else{
someOtherObject.maxChars = 100;
}
break;
case someOtherObject:
break;
}
}
So basically, as the user types into tf, I'm making sure they have entered at least 10 characters. If they were to meet the condition, and then erase a character, the event would be fired again, and the condition would not be met, so someOtherObject is disabled.