Dynamically create button in Flex - actionscript-3

I have very basic question about Flex SDK, but I didn't find any resources for my problem and honestly don't know if it even possible to do what I want. So here is my question:
I created Flex project with Adobe Flex Builder 4.6. Then I placed the button (let's say it's id is btn1) in main MXML file. I want to create second button dynamically right from the script part of main MXML file. Specifically I want to create it from button click handler of btn1.
Here is my MXML code (it is the only file in project ):
<?xml version="1.0" encoding="utf-8"?>
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx"
minWidth="955" minHeight="600">
<fx:Script>
<![CDATA[
protected function btn1_clickHandler(event:MouseEvent):void
{
var btn2:Button = new Button();
btn2.label = "Hello";
btn2.x = 50;
btn2.y = 50;
}
]]>
</fx:Script>
<fx:Declarations>
<!-- Non visual elements -->
</fx:Declarations>
<s:Button id="btn1"
x="10" y="10"
label="Кнопка"
click="btn1_clickHandler(event)"/>
</s:Application>
But when I click btn1 - nothing happens. It is possible that I don't understand something in flex programming paradigm - please point it out for me.

You have to add the button to the view using addElement().
var btn2:Button = new Button();
btn2.label = "Hello";
btn2.x = 50;
btn2.y = 50;
addElement(btn2);

Related

Hide a Button in a ButtonBar

I was wondering if there is any way you hide a particular button in a ButtonBar. According to this answer (and the link provided in the second answer) Disable individual buttons in a buttonbar I need to use the getChildAt method of the ButtonBar, but when I do that I get the custom skin object and not the Button object. I was wondering how I could get access to the Button object.
Thanks!
Under the assumption that all buttons in your button bar will be rendered at the same time and you won't need scrollbars...
With a Spark ButtonBar, you can access the skin part directly to get access to a button. Conceptually something like this:
var button : Button = mySparkButtonBarInstance.dataGroup.getElementAt(SomeIndex);
button.visible = false; // or true
button.includeInLayout = false; // or true
This won't work if your ButtonBar can make use of Virtual Layouts and requires scrolling.
Edit: Here is working code demonstrating this technique:
<?xml version="1.0" encoding="utf-8"?>
<s:WindowedApplication xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx">
<fx:Script>
<![CDATA[
import mx.core.IVisualElement;
protected function button1_clickHandler(event:MouseEvent):void
{
trace(buttonBar.dataGroup.getElementAt(0));
var button :IVisualElement = buttonBar.dataGroup.getElementAt(0);
button.visible = false; // or true
button.includeInLayout = false; // or true }
}
]]>
</fx:Script>
<fx:Declarations>
<!-- Place non-visual elements (e.g., services, value objects) here -->
</fx:Declarations>
<s:layout>
<s:VerticalLayout paddingLeft="20" paddingTop="20"/>
</s:layout>
<s:ButtonBar id="buttonBar">
<mx:ArrayCollection>
<fx:String>Flash</fx:String>
<fx:String>Director</fx:String>
<fx:String>Dreamweaver</fx:String>
<fx:String>ColdFusion</fx:String>
</mx:ArrayCollection>
</s:ButtonBar>
<s:Button label="Remove" click="button1_clickHandler(event)" />
</s:WindowedApplication>

Flashbuilder 4, Desktop Air Application - Embed and play Sound

I am a complete newbie to Flashbuilder, and I need to learn how to 1.) Embed a sound file (mp3) and 2.) be able to play said file.
I looked it up using Google and all the examples seem to be for AS3, I tried to adapt it as follows but cant get it to play (or should I say I can't hear anything?)
bgmusic is imported at the src level
Test.mxml:
<?xml version="1.0" encoding="utf-8"?>
<s:WindowedApplication xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx">
<fx:Declarations>
<!-- Place non-visual elements (e.g., services, value objects) here -->
</fx:Declarations>
<fx:Script>
<![CDATA[
import flash.media.Sound;
[Embed(source="bgmusic.mp3")]
public var mySound:Class;
protected function button1_clickHandler(event:MouseEvent):void
{
var s:Sound = new mySound() as Sound;
s.play();
}
]]>
</fx:Script>
<s:Button label="Test" click="button1_clickHandler(event)" />
</s:WindowedApplication>

Access object inside View from another View?

applicationX.mxml :
<?xml version="1.0" encoding="utf-8"?>
<s:TabbedViewNavigatorApplication xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark" applicationDPI="160" >
<s:ViewNavigator label="Login" width="100%" height="100%" firstView="views.LoginView" />
<s:ViewNavigator label="Settings" width="100%" height="100%" firstView="views.SettingsView" />
</s:TabbedViewNavigatorApplication>
Settings.mxm ( Settings View ) :
<s:View xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark" >
<s:Label id="myLabel" />
</View>
How to access myLabel from Login view ?
you shouldn't. One view should never know what is inside another view. What you want is a model with a property like .loginStatus that can then be set by Login and seen by Settings. You can use one of many MVC styles to accomplish this. Do some googling on MVC patterns and Flex and see the different ways this is done. In the meantime, here is a quick for instance:
Settings.mxml:
<s:View xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark" >
<fx:Script>
<![CDATA[
private var model:MyModel = MyModel.getInstance();
]]>
</fx:Script>
<s:Label id="myLabel" text="{model.loggedInStatus}" />
</View>
Login.mxml:
<s:View xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark" >
<fx:Script>
<![CDATA[
private var model:MyModel = MyModel.getInstance();
private function loginSucceded():void{
model.loggedInStatus="Logged In";
}
]]>
</fx:Script>
</View>
MyModel.as
Singleton class with a property named .loggedInStatus. You can check this other answer AS3 singleton implementations for a discussion about various singleton patterns and why I use the one I use.
This is a VERY simple example. You wouldn't want to use a human readable string loggedInStatus to determine state or anything. but this is an example of how the model works and how views can display proper things based on the state of the model.
Set settings singleton. This means, you define a static variable pointing to the item itself (it is required to have only one instance of Settings.mxml)
add
public static var instance:Settings;
to settings.
add initializeEventListener to settings, and inside the function set the instance:
instance=this;
Than you can access Settings page anytime by getting the singleton, like:
Settings.instance.myLabel.text="success";

Apply effect on window in Flex, Air, AS3

I'm looking to animate a popup window using the effect.
The problem is that the effect is applied to the content of the popup window, not the popup window itself (including the title bar, minimize, maximize buttons etc)
Have a look at the result here..
My code is really simple and logically, should work if it is possible to animate a window.
<?xml version="1.0" encoding="utf-8"?>
<s:WindowedApplication xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx">
<fx:Script>
<![CDATA[
import comps.MyWin;
[Bindable]
private var _win:MyWin;
protected function openPopup():void
{
_win = new MyWin();
_win.width = 300;
_win.height = 300;
_win.open();
}
protected function animatepopup():void
{
MyEffect.play();
}
]]>
</fx:Script>
<fx:Declarations>
<s:Move id="MyEffect" xFrom="{_win.x}" xTo="{_win.x + 150}" target="{_win}"/>
</fx:Declarations>
<s:layout>
<s:VerticalLayout/>
</s:layout>
<s:Button label="Open" click="openPopup()"/>
<s:Button label="Animate" click="animatepopup()"/>
</s:WindowedApplication>
I think you need to target the object's NativeWindow instance in order to move and resize the object.
Thus, replace _win.myProperty with _win.stage.nativeWindow.myProperty:
<s:Move id="MyEffect" xFrom="{_win.stage.nativeWindow.x}" xTo="{_win.stage.nativeWindow.x + 150}" target="{_win.stage.nativeWindow}"/>
Then, the animation will affect the NativeWindow and not the internals of the window.

Flex custom component, best way to use it

I have not completly understood how custom components work...
Let's assume I have my Main.mxml application
<?xml version="1.0" encoding="utf-8"?>
<s:WindowedApplication xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx"
xmlns:local="*">
<fx:Script>
<![CDATA[
private var privateStr:String = "Stringa Private";
public var publicStr:String = "Stringa Public";
]]>
</fx:Script>
<local:AddUser height="100" width="500"/>
<s:Label id="lblText" x="120" y="120" width="418" height="115" text="!!!"/>
</s:WindowedApplication>
And the component AddUser.mxml
<?xml version="1.0" encoding="utf-8"?>
<mx:VBox
xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx"
creationComplete="initialize_component()">
<fx:Script>
<![CDATA[
public var btnName:String = "Login";
private function initialize_component():void
{
login.label = btnName;
}
private function doLogin():void
{
//some stuff here
}
]]>
</fx:Script>
<s:TextInput id="txtuser" x="96" y="36"/>
<s:TextInput id="txtpass" x="96" y="66"/>
<s:Button id="login" x="96" y="96" width="128" click="doLogin()" />
</mx:VBox>
I would like that on the Button (login) click I get the publicStr/privateStr that are in the main.mxml...
Am I getting everything wrong? how can I use more components like they are all part of the same application and use the same variables/methods?
It seems like you're having issues with the idea of encapsulation. Child components shouldn't know about parent components, and View components shouldn't do real work, only request work from Controller components. In very simple projects, your top level component can contain the controller logic, but many people prefer to keep it separate even in small projects. How to do this is beyond the scope of this answer.
So, how should the parent and child properly communicate? Child components should expose properties that the parent (or Framework, if you're feeling ready to use a dependency injection framework) can populate with only the data the child components need.
Child components request work from the controller by generating events.
So, doLogin() would containe something like
dispatchEvent(new Event('doLogin'));
and the parent component would be listening for this Event. In its handler, you would perform the login. More than likely, your login would be asynchronous, so you'll need another handler to listen for the login data to come back. When the login data comes back, you will then set the properties on the login View based on the return.