I want to show the busyIndicator before launching a HTTPService , and hide it when the rpc is finished :
<?xml version="1.0" encoding="utf-8"?>
<s:View xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:mx="library://ns.adobe.com/flex/mx"
xmlns:s="library://ns.adobe.com/flex/spark"
title="Saisie et envoi"
creationComplete="creationCompleteHandler(event)" >
<fx:Declarations>
<!-- Placer ici les éléments non visuels (services et objets de valeur, par exemple). -->
<mx:HTTPService id="userRequest" url="{url}/crr.php" resultFormat="text" result="userRequest_resultHandler(event)" useProxy="false" method="POST" />
</fx:Declarations>
<fx:Script>
<![CDATA[
import mx.events.FlexEvent;
import mx.rpc.events.ResultEvent;
import model.Config;
import model.Db;
var conf:Config = new Config();
public var db:Db = new Db();
[Bindable]
public var url:String = conf.getConfigSo("url"); // example : http://localhost/myfolder
protected function enregistrer(event:MouseEvent):void
{
var param:Object = new Object();
try {
if (db.avoirAttribut("enreg")) {
db.setDbSo("enreg", db.getDbSo("enreg")+chp1.text+";"+chp2.text+"\n");
}
else {
db.setDbSo("enreg", chp1.text+";"+chp2.text+"\n");
}
param.text = "Enregistrement effectué avec succès !";
navigator.pushView(Message, param);
}
catch (e:Error) {
param.text = "Enregistrement non effectué !";
navigator.pushView(Message, param);
}
}
protected function lire(event:MouseEvent):void
{
area.text = db.getDbSo("enreg");
}
protected function send(event:MouseEvent):void
{
busy.visible = true;
userRequest.cancel();
var params:Object = new Object();
params.col1 = db.getDbSo("enreg");
userRequest.send(params);
busy.visible = false;
}
protected function userRequest_resultHandler(event:ResultEvent):void
{
resultHTTP.text = userRequest.lastResult.toString();
}
protected function creationCompleteHandler(event:FlexEvent):void
{
chp1.setFocus();
}
]]>
</fx:Script>
<s:Scroller width="100%" height="100%">
<s:VGroup width="100%" height="100%" paddingTop="5" paddingBottom="5" verticalAlign="middle" horizontalAlign="center" gap="5">
<s:TextInput id="chp1" width="50%"/>
<s:TextInput id="chp2" width="50%"/>
<s:Button label="Enregistrer" click="enregistrer(event)"/>
<s:Button label="Lire" click="lire(event)"/>
<s:TextArea id="area" editable="false"/>
<s:Button label="Envoyer" click="send(event)"/>
<s:BusyIndicator id="busy" symbolColor="blue" visible="false" />
<s:Label id="resultHTTP"/>
</s:VGroup>
</s:Scroller>
</s:View>
The problem is that at runtime the BusyIndicator is not shown , though I realise that it took some seconds for the entire operation to complete. So why is not the BusyIndicator shown in this case ?
The HTTPService request send() returns when the request is sent, not when the response is received. So you are showing the busy indicator only for a short period of time (and actually not at all, since the rendering is done in the next display cycle...)
What you need to do is to make the indicator visible in the send function as you're doing, but hide the indicator on the result handler. (You should do this for the error handler as well, otherwise the indicator will still be visible if there was an error in the request)
Related
I'm facing a pretty basic but irksome problem with my Flex program.
To make the long story short, I've a DataGrid where in every row (you can already add and remove rows dinamically) there's a Combobox based on an ArrayCollection of elements (responsabili), every change to the Combobox already stores changes to the db.
I want the Combobox to show the value loaded from the db as the selected value.
<s:Panel title="qqq" width="100%" height="100%" styleName="light">
<s:layout>
<s:VerticalLayout paddingBottom="10" paddingLeft="10" paddingRight="10" paddingTop="10" />
</s:layout>
<s:VGroup width="100%" height="100%">
<mx:Text text="www" />
<components:GraphicButton styleName="add" toolTip="Aggiungi elemento" id="aggCompito" click="aggCompito_clickHandler(event)"/>
<s:DataGrid width="100%" height="100%" dataProvider="{MyModel.instance.compiti}" editable="true" gridItemEditorSessionSave="changeHandler(event)">
<s:columns>
<s:ArrayList>
<s:GridColumn headerText="Responsabile" editable="false" width="180">
<s:itemRenderer>
<fx:Component>
<s:GridItemRenderer>
<fx:Script>
<![CDATA[
import it.aaa.frontend.model.MyModel;
import mx.binding.utils.ChangeWatcher;
import mx.collections.ArrayCollection;
import mx.controls.Alert;
import mx.core.FlexGlobals;
import mx.events.CloseEvent;
import mx.events.IndexChangedEvent;
import spark.events.IndexChangeEvent;
protected function changeHandler(event:IndexChangeEvent):void {
data.responsabile = myResponsabile.selectedItem;
// TODO Auto-generated method stub
data.tipo = event.newIndex;
dispatchEvent(new Event("compitiChange", true));
}
protected function responsabililabelFunc(item:Object):String {
return String(item.cognome) + " " + String(item.nome);
}
protected function guessSelectedItem(item:Object):int {
return item.responsabile.id;
}
]]>
</fx:Script>
<s:HGroup>
<s:ComboBox id="myResponsabile"
dataProvider="{MyModel.instance.responsabili}"
change="changeHandler(event)"
labelFunction="responsabililabelFunc"
selectedItem="{data.responsabile}"
/>
</s:HGroup>
</s:GridItemRenderer>
</fx:Component>
</s:itemRenderer>
</s:GridColumn>
</s:ArrayList>
</s:columns>
</s:DataGrid>
</s:VGroup>
</s:Panel>
MyModel.as
public var responsabili:ArrayCollection; //initialized with actual ArrayCollection of "responsabili", with id, cognome, nome.
It will only work with selectedItem="{data.responsabile}" if you are using some actionscript classes as your data object and the property resposabile is marked as bindable:
[Bindable] public var responsabile:Object;
If you have just some generic objects as data, you will need to catch this up where data is set in your itemrenderer. So your GridItemRenderer needs another method:
override public function set data(value:Object):void
{
super.data = value;
// only do something if the data is set. When the renderer is destroyed the data will be null
if (data)
{
myResponsabile.selectedItem = data.responsabile;
}
}
I don't remember though if the data is set after all components (including your combobox) has been created or before that. So in case you will get a null pointer exception because myResponsabile is null at this point, it will get more complicated:
private var _myResponsabile:Object;
private var _myResponsabileChanged:Boolean;
override public function set data(value:Object):void
{
super.data = value;
// only do something if the data is set. When the renderer is destroyed the data will be null
if (data)
{
_myResponsabile = data.responsabile;
_myResponsabileChanged = true;
invalidateProperties();
}
}
override protected function commitProperties():void
{
super.commitProperties();
if(_myResponsabileChanged)
{
_myResponsabileChanged = false;
myResponsabile.selectedItem = _myResponsabile;
}
}
I've reached the point where I have got a dropdown in which is embedded a tree. Each node has got a checkbox.
The idea is to be able to navigate and tick the checkboxes without having the dropdown closing.
Can't make this dropdown to remain open after a checkbox has been clicked!
The event that closes the dropdown occurs when the xml is updated in PermissionTreeItemRendererV2.as > handleChkClick(evt) > this.itemXml.#checked = {"0" or "1"};
Any idea how to tweak the code to disable this annoying event?
sample_combobox.mxml:
<?xml version="1.0"?>
<mx:Application xmlns:local="local.*"
xmlns:mx="http://www.adobe.com/2006/mxml"
creationComplete="loadXML()">
<mx:Script>
<![CDATA[
import mx.collections.XMLListCollection;
import mx.rpc.events.ResultEvent;
import mx.rpc.http.mxml.HTTPService;
public var xmlService:HTTPService = new HTTPService();
[Bindable]
public var xmlResult:XML;
[Bindable]
public var xmlList:XMLList;
[Bindable]
public var xmlTeams:XMLListCollection;
public function loadXML():void
{
xmlService.url = "mlb.xml"
xmlService.resultFormat = "e4x";
xmlService.addEventListener(ResultEvent.RESULT, resultHandler);
xmlService.send();
}
public function resultHandler(event:ResultEvent):void
{
xmlResult = XML(event.result);
xmlList = xmlResult.league;
xmlTeams = new XMLListCollection(xmlList);
}
]]>
</mx:Script>
<local:TreeComboBox
width="300"
id="combo"
labelField="#label" dataProvider="{xmlTeams}" />
</mx:Application>
TreeCombobox.mxml:
<?xml version="1.0" encoding="utf-8"?>
<local:ComboBoxNoClose xmlns:mx="http://www.adobe.com/2006/mxml"
xmlns:local="local.*">
<mx:Script>
<![CDATA[
import mx.events.FlexEvent;
[Bindable]
private var _label:String;
[Bindable]
public var treeSelectedItem:Object;
public function updateLabel(event:*):void
{
_label = event.currentTarget.selectedItem[this.labelField];
treeSelectedItem = event.currentTarget.selectedItem;
}
override protected function updateDisplayList(unscaledWidth:Number,
unscaledHeight:Number):void
{
super.updateDisplayList(unscaledWidth, unscaledHeight);
if(dropdown && _label != null){
text = "";//_label;
}
}
]]>
</mx:Script>
<local:dropdownFactory>
<mx:Component>
<mx:Tree change="outerDocument.updateLabel(event)" height="500"
width="500"
itemRenderer="local.PermissionsTreeItemRendererV2"
folderClosedIcon="{null}"
folderOpenIcon="{null}"
defaultLeafIcon="{null}" />
</mx:Component>
</local:dropdownFactory>
</local:ComboBoxNoClose>
PermissionTreeItemRendererV2.as
// ActionScript file
package local
{
import flash.events.Event;
import flash.events.MouseEvent;
import mx.collections.ArrayCollection;
import mx.collections.ArrayList;
import mx.collections.ListCollectionView;
import mx.controls.CheckBox;
import mx.controls.treeClasses.TreeItemRenderer;
import mx.controls.treeClasses.TreeListData;
public class PermissionsTreeItemRendererV2 extends TreeItemRenderer{
public var chk:CheckBox;
public var itemXml:XML;
public function PermissionsTreeItemRendererV2(){
super();
mouseEnabled = false;
}
override public function set data(value:Object):void{
if(value != null){
super.data = value;
this.itemXml = XML(value);
if(this.itemXml.#checked == "1"){
this.chk.selected = true;
}else{
this.chk.selected = false;
}
}
}
override protected function createChildren():void{
super.createChildren();
chk = new CheckBox();
chk.addEventListener(MouseEvent.CLICK, handleChkClick);
addChild(chk);
}
override protected function updateDisplayList(unscaledWidth:Number, unscaledHeight:Number):void{
super.updateDisplayList(unscaledWidth,unscaledHeight);
if(super.data){
var tld:TreeListData = TreeListData(super.listData);
//In some cases you only want a checkbox to appear if an
//item is a leaf
//if so, then keep the following block uncommented,
//otherwise you can comment it out to display the checkbox
//for branch nodes
if(tld.hasChildren){
this.chk.visible = true;
}else{
//You HAVE to have the else case to set visible to true
//even though you'd think the default would be visible
//it's an issue with itemrenderers...
this.chk.visible = true;
}
if(chk.visible){
//if the checkbox is visible then
//reposition the controls to make room for checkbox
this.chk.x = super.label.x
super.label.x = this.chk.x + 17;
this.chk.y = super.label.y+8;
}
}
}
private function handleChkClick(evt:MouseEvent):void
{
if(this.chk.selected)
{
this.itemXml.#checked = "1";
}
else
{
this.itemXml.#checked = "0";
}
}
}
}
ComboboxNoClose.as:
package local
{
import flash.events.Event;
import flash.events.MouseEvent;
import mx.controls.CheckBox;
import mx.controls.ComboBox;
import mx.events.DropdownEvent;
import mx.events.ListEvent;
public class ComboBoxNoClose extends ComboBox
{
public function ComboBoxNoClose()
{
super();
}
public function onOpen(event:Event):void
{
event.stopImmediatePropagation();
}
public override function close(trigger:Event = null):void
{
if (trigger != null)
{
super.close();
}
}
}
}
mlb.xml that populates the tree:
<?xml version="1.0" encoding="utf-8"?>
<root>
<league label="American League">
<division label="West">
<team label="Los Angeles" />
<team label="Seattle" />
<team label="Oakland" />
<team label="Texas" />
</division>
<division label="Central">
<team label="Cleveland" />
<team label="Detroit" />
<team label="Minnesota" />
<team label="Chicago" />
<team label="Kansas City" />
</division>
<division label="East">
<team label="Boston" />
<team label="New York" />
<team label="Toronto" />
<team label="Baltimore" />
<team label="Tampa Bay" />
</division>
</league>
</root>
Default behavior of popup is that, when you click on dropdown it closes it self. You can solve this problem like this
<mx:PopUpButton id="popup" width="100%" label="{label}" close="popup_closeHandler(event)" open="popup_openHandler(event)" openAlways="true">
<mx:popUp>
<mx:VBox width="{popup.width*1.25}" mouseEnabled="false" verticalGap="1">
<mx:List id="listSelectAll" width="100%" rowCount="1" selectable="true" itemClick="listSelectAll_itemClickHandler(event)">
<mx:dataProvider>
<mx:Array>
<mx:Object id="selectAll" selected="" label="All"/>
</mx:Array>
</mx:dataProvider>
<mx:itemRenderer>
<mx:Component>
<mx:HBox width="100%" height="100%" mouseChildren="false">
<mx:CheckBox selected="{data.selected}" label="{data.label}" width="100%"/>
</mx:HBox>
</mx:Component>
</mx:itemRenderer>
</mx:List>
<mx:List id="listItems" width="100%" dataProvider="{_dataProvider}" itemClick="listItems_itemClickHandler(event)" variableRowHeight="true">
<mx:itemRenderer>
<mx:Component>
<!--
<mx:HBox width="100%" height="100%" mouseChildren="false" verticalAlign="middle">
<mx:CheckBox selected="{data[outerDocument.selectedField]}" label="{data[outerDocument.labelField]}" width="100%"/>
</mx:HBox>
-->
<mx:HBox width="100%" mouseChildren="false" verticalAlign="middle" horizontalAlign="left" paddingLeft="4">
<mx:Script>
<![CDATA[
override public function set data(value: Object) : void {
super.data = value;
if(data.iconCache == null || outerDocument.cacheIcon == false) {
imgIcon.source = data[outerDocument.iconField];
} else {
imgIcon.source = new Bitmap(data.iconCache);
}
}
protected function image_ioErrorHandler(event:IOErrorEvent):void {
imgIcon.visible = imgIcon.includeInLayout = false;
}
protected function imgIcon_completeHandler(event:Event):void {
imgIcon.visible = imgIcon.includeInLayout = true;
if(outerDocument.cacheIcon) {
var bitmapData:BitmapData = Bitmap(imgIcon.content).bitmapData;
//var bitmap:Bitmap = new Bitmap(bitmapData);
data.iconCache = bitmapData;
//imgIcon.removeEventListener(Event.COMPLETE, imgIcon_completeHandler);
}
}
]]>
</mx:Script>
<mx:CheckBox id="chkSelected" selected="{data[outerDocument.selectedField]}"/>
<mx:Image id="imgIcon" width="{outerDocument.iconWidth}" height="{outerDocument.iconHeight}" visible="{data[outerDocument.iconField]}" includeInLayout="{data[outerDocument.iconField]}" complete="imgIcon_completeHandler(event)" ioError="image_ioErrorHandler(event)"/>
<mx:Label id="lblText" text="{data[outerDocument.labelField]}"/>
</mx:HBox>
</mx:Component>
</mx:itemRenderer>
</mx:List>
</mx:VBox>
</mx:popUp>
</mx:PopUpButton>
or you can visit my post for a complete implementation. here
Please help
I can save the data from the three components as xml and it works, but now I am struggling with the code to read that data back into the components when the user opens. This is a local file that is created by the user. I need help with the open event handler.
<?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"
width="734" height="389"
creationComplete="init();">
<fx:Declarations>
<!-- Place non-visual elements (e.g., services, value objects) here -->
</fx:Declarations>
<fx:Script>
<![CDATA[
[Bindable]
public var xmlData:XML=<ROOTS></ROOTS>;
private function fnAddItem():void
{
var fr:FileReference = new FileReference();
var ba:ByteArray = new ByteArray();
var newXmlRow:XML=<ROOTS>
<TXT>{txt1.text}</TXT>
<TXTA>{txt2.text}</TXTA>
<DTF>{txt3.text}</DTF>
</ROOTS>;
ba.writeMultiByte(newXmlRow, 'utf-8');
fr.save(ba);
}
protected function oped_clickHandler(event:MouseEvent):void
{
var fr:FileReference = new FileReference();
var ba:ByteArray = new ByteArray();
var newXmlRow:XML=<ROOTS>
<TXT>{txt1.text}</TXT>
<TXTA>{txt2.text}</TXTA>
<DTF>{txt3.text}</DTF>
</ROOTS>;
ba.readMultiByte(xmlData, 'utf-8');
fr.load(ba);
}
]]>
</fx:Script>
<s:Label x="108" y="80" text="Name"/>
<s:Label x="91" y="222" text="Remarks"/>
<s:Label x="108" y="116" text="text"/>
<s:TextInput id="txt1" x="167" y="78"/>
<s:TextArea id="txt2" x="167" y="218" height="86"/>
<s:TextArea id="txt3" x="167" y="108" height="77"/>
<s:Button x="53" y="242" label="save" width="90" click="fnAddItem()"/>
<s:Button id="oped" x="73" y="271" label="open" click="oped_clickHandler(event)"/>
</s:WindowedApplication>
first if you want a dialog you have to wait for the user to make a selection. The selection throws an event that you can catch. Within the handler you can do the file handling. Try if the following code works for you.
private var openedFile:File;
private function oped_clickHandler(event:MouseEvent):void {
openedFile = new File();
openedFile.addEventListener(Event.SELECT, file_select);
openedFile.browseForOpen("Please select a file...");
}
private function file_select(event:Event):void {
if(openedFile != null && openedFile.exists){
var fileStream:FileStream = new FileStream();
fileStream.open(openedFile, FileMode.READ);
var readXML:XML = XML(fileStream.readUTFBytes(fileStream.bytesAvailable));
fileStream.close();
trace(readXML.toString());
txt1.text = readXML.TXT;
txt2.text = readXML.TXTA;
txt3.text = readXML.DTF;
}
trace(event);
}
cheers,
rob
Hello I'm building a chat using Flex. The problem is how to do that new user get the list off all users online and added to the lists of all users. I try to put this information in DataGrid through dataProvider "callerns":
<s:DataGrid x="10" y="125" width="238" height="125" alternatingRowColors="[ #67676767, #555555]"
borderVisible="true" chromeColor="#555555" color="#CCCCCC"
contentBackgroundColor="#555555" dataProvider="{callerns}" fontWeight="bold"
requestedRowCount="4" rollOverColor="#08700D" selectionColor="#08700D"
symbolColor="#CCCCCC">
<s:columns>
<s:ArrayList>
<s:GridColumn dataField="name" headerText="USER ONLINE"></s:GridColumn>
<s:GridColumn dataField="peerID" headerText="USER ID"></s:GridColumn>
</s:ArrayList>
</s:columns>
</s:DataGrid>
Here is the part of code:
[Bindable]
private var callerns:ArrayCollection = new ArrayCollection();
...........
private function netStatusEvent(event:NetStatusEvent):void{
trace('NetConnection status event (1): ' + event.info.code);
//writeText(event.info.code);
switch(event.info.code){
case "NetConnection.Connect.Success":
log('Connected (NearID: '+nc.nearID+')', 'debug');
log('Connection sucsessful');
MyPeerID = nc.nearID;
txtFingerprint.text = MyPeerID;
initSendNetStream();
callerns.addItem({peerID: MyPeerID, name: myName});
setupGroup();
break;
case "NetGroup.Posting.Notify":
receiveMessage(event.info.message);
log('Message posted');
break;
case "NetGroup.Connect.Success":
log('Net Group connection sucsessful');
connected = true;
break;
case 'NetStream.Connect.Success':
log('Peer Connected (FarID: '+event.info.stream.farID+')', 'debug');
break;
case "NetGroup.Neighbor.Connect":
log('New user connected');
break;
}
}
private function initSendNetStream():void{
trace("initSendStream");
sendStream = new NetStream(nc,NetStream.DIRECT_CONNECTIONS);
sendStream.addEventListener(NetStatusEvent.NET_STATUS, netStatusEvent);
var clientObject:Object = new Object();
clientObject.onPeerConnect = function(callerns:NetStream):Boolean{
initRecvStream(callerns.farID);
callerns.send('onPeerNameUpdate', MyPeerID, myName);
return true;
}
sendStream.client = clientObject;
sendStream.publish('video');
log('Net Stream publish start');
}
private function initRecvStream(peerID:String):void {
//log('initRecvStream', 'debug');
var stream:NetStream = new NetStream(nc, peerID);
stream.addEventListener(NetStatusEvent.NET_STATUS, netStatusEvent);
stream.play('video');
var client:Object = new Object();
client.onPeerNameUpdate = onPeerNameUpdate;
stream.client = client;
var peer:Object = new Object();
peer.stream = stream;
recvStreams[peerID] = peer;
}
private function onPeerNameUpdate(peerID:String, name:String):void {
//log('onPeerNameUpdate received: '+peerID+':'+name, 'debug');
//log(name+' connected to your channel', 'debug');
callerns.addItem({peerID: peerID, name: name});
}
Unfortunately this doesn't work and new users aren't added to the grid. Could you please help me to solve this problem?
Removed original post seems I'm wrong, this works:
<?xml version="1.0" encoding="utf-8"?>
<s:Group creationComplete="group1_creationCompleteHandler(event)"
height="100%"
width="100%"
xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:mx="library://ns.adobe.com/flex/mx"
xmlns:s="library://ns.adobe.com/flex/spark">
<fx:Declarations>
<!-- Place non-visual elements (e.g., services, value objects) here -->
</fx:Declarations>
<fx:Script>
<![CDATA[
import mx.collections.ArrayCollection;
import mx.events.FlexEvent;
[Bindable]
private var callerns : ArrayCollection;
protected function group1_creationCompleteHandler(event : FlexEvent) : void
{
callerns = new ArrayCollection();
}
protected function addItemClickHandler(event : MouseEvent) : void
{
callerns.addItem({peerID: "somePeerID", name: "someName"});
}
]]>
</fx:Script>
<s:layout>
<s:VerticalLayout/>
</s:layout>
<s:Button click="addItemClickHandler(event)"
label="Add Item"/>
<s:Button click="propertyChangeClickHandler(event)"
label="Dispatch Property Change"/>
<s:DataGrid alternatingRowColors="[ #67676767, #555555]"
borderVisible="true"
chromeColor="#555555"
color="#CCCCCC"
contentBackgroundColor="#555555"
dataProvider="{callerns}"
fontWeight="bold"
height="125"
requestedRowCount="4"
rollOverColor="#08700D"
selectionColor="#08700D"
symbolColor="#CCCCCC"
width="238"
x="10"
y="125">
<s:columns>
<s:ArrayList>
<s:GridColumn dataField="name"
headerText="USER ONLINE">
</s:GridColumn>
<s:GridColumn dataField="peerID"
headerText="USER ID">
</s:GridColumn>
</s:ArrayList>
</s:columns>
</s:DataGrid>
</s:Group>
So I was originally wrong, hitting the button does cause an update to the grid. It would have been extremely helpful if you had posted a link to the original tutorial you were building off of, I found it and got it working with spark just fine. I'm assuming you got this part figured out already but here's the basic chat client:
<?xml version="1.0" encoding="utf-8"?>
<s:Application minHeight="600"
minWidth="955"
xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:mx="library://ns.adobe.com/flex/mx"
xmlns:s="library://ns.adobe.com/flex/spark">
<fx:Declarations>
<!-- Place non-visual elements (e.g., services, value objects) here -->
</fx:Declarations>
<fx:Script>
<![CDATA[
private const SERVER_ADDRESS : String = "rtmfp://p2p.rtmfp.net/";
private const DEVELOPER_KEY: String = PUT_YOUR_DEV_KEY_HERE;
private var nc : NetConnection;
private var myPeerID : String;
private var farPeerID : String;
// streams
private var sendStream : NetStream;
private var recvStream : NetStream;
private function initConnection() : void
{
if (txtFingerprint.text)
{
farPeerID = txtFingerprint.text;
}
nc = new NetConnection();
nc.addEventListener(NetStatusEvent.NET_STATUS, ncStatus);
nc.connect(SERVER_ADDRESS + DEVELOPER_KEY);
}
private function ncStatus(event : NetStatusEvent) : void
{
trace(event.info.code);
myPeerID = nc.nearID;
txtFingerprint.text = myPeerID;
}
private function initSendStream() : void
{
trace("initSendStream");
sendStream = new NetStream(nc, NetStream.DIRECT_CONNECTIONS);
sendStream.addEventListener(NetStatusEvent.NET_STATUS, netStatusHandler);
sendStream.publish("media");
var sendStreamClient : Object = new Object();
sendStreamClient.onPeerConnect = function(callerns : NetStream) : Boolean
{
farPeerID = callerns.farID;
trace("onPeerConnect " + farPeerID);
return true;
}
sendStream.client = sendStreamClient;
}
private function initRecvStream() : void
{
recvStream = new NetStream(nc, farPeerID);
recvStream.addEventListener(NetStatusEvent.NET_STATUS, netStatusHandler);
recvStream.play("media");
recvStream.client = this;
}
public function receiveSomeData(str : String) : void
{
txtReceiveData.text = str;
}
private function sendSomeData() : void
{
sendStream.send("receiveSomeData", txtSendData.text);
}
private function netStatusHandler(event : NetStatusEvent) : void
{
trace(event.info.code);
}
]]>
</fx:Script>
<mx:TextInput id="txtFingerprint"
width="391"
x="10"
y="10"/>
<mx:Button click="initConnection()"
label="Connect"
x="409"
y="10"/>
<mx:TextInput id="txtSendData"
x="10"
y="40"/>
<mx:TextInput id="txtReceiveData"
width="251"
x="10"
y="70"/>
<mx:Button click="sendSomeData()"
label="Send data"
x="178"
y="40"/>
<mx:Button click="initSendStream()"
label="initSendStream"
x="10"
y="100"/>
<mx:Button click="initRecvStream();"
label="initReceiveStream"
x="132"
y="100"/>
<mx:Text height="122"
text="Hint: First running Flash app - click Connect to get Fingerprint PeerID. Copy and paste this PeerID to second running Flash app to the same field and click Connect. Then initSendStream and initReceiveStream on both of them and finally you can write some text and click Send data."
width="391"
x="10"
y="130"/>
</s:Application>
Get a developer key here:
http://www.adobe.com/cfusion/entitlement/index.cfm?e=cirrus
I'm not sure what's going wrong but as the commenter above says you need to include how exactly it's breaking, that is what happens when you debug (be sure to install the debug flash player for whatever browser your using, beware chrome manages it's own plugin by default) what do you see in the console, do you get any errors etc. The tutorial app works fine for me, having this deal with two way communication and maintaining a list of all connected peers seems to be the goal correct? I also don't understand the question about NetGroup, there's more on P2P that covers that here though:
http://www.adobe.com/devnet/flashmediaserver/articles/p2p_rtmfp_groups.html
I wish you would have included more information about where you started and where you're headed with all this though (and code, I always want more code :)
I'm working on a flash cards application and am using an ArrayCollection of Objects to store each cards individual data. When the user click the 'save' button, the text from the two textAreas and the 'title' textinput are stored in the AC as one object with .title, .side1 and .side2 properties that contain the text from the flash card.
I have made a List in a separate class I want to have display the title of each card the user has created, but after days of researching and looking around, I still cannot get the display to list the titles.
If anyone could point me in the right direction it would very appreciated.
Part of my NewCard.mxml:
<?xml version="1.0" encoding="utf-8"?>
<fx:Script>
<![CDATA[
import flash.events.EventDispatcher;
import mx.collections.ArrayCollection;
import spark.effects.SlideViewTransition;
import views.MyCards;
protected function button1_clickHandler(event:MouseEvent):void // back button
{
{
navigator.pushView(views.MyFlashCardsHome, event.relatedObject);
}
}
protected function button2_clickHandler(event:MouseEvent):void // save button
{
var myc:MyCards = new MyCards();
var card:Object = new Object();
myc.add();
titleCard.text = "Card Added!";
}
protected function button3_clickHandler(event:MouseEvent):void // flip button
{
rotateEffect.play();
if(rotateEffect.isPlaying)
{
if(mtext1.visible)
{
mtext2.visible = true;
mtext1.visible = false;
//mtext2.text = "two";
groupt.layoutDirection = "rtl";
}
else
{
mtext2.visible = false;
mtext1.visible = true;
//mtext1.text = "one";
groupt.layoutDirection = "rtl";
}
}
}
protected function button4_clickHandler(event:MouseEvent):void // push home button
{
var slideViewTransition:SlideViewTransition = new SlideViewTransition( 300, SlideViewTransition.SLIDE_RIGHT);
navigator.pushView(views.HomePage, event.relatedObject, slideViewTransition);
}
]]>
</fx:Script>
<fx:Declarations>
<s:Rotate3D id="rotateEffect" duration="300" target="{groupt}"
angleYFrom="0" angleYTo="180"
autoCenterTransform="true"
effectStart="flipButton.enabled=false;"
effectEnd="flipButton.enabled=true;"/>
</fx:Declarations>
<s:actionContent>
<s:Button height="50" label="Study" click="button1_clickHandler(event)" cornerRadius="0"
fontFamily="_sans"/>
<s:Button height="62" click="button4_clickHandler(event)" cornerRadius="0" skinClass="skins.homeButtonSkin"/>
</s:actionContent>
<s:Image x="0" y="-80" width="1024" height="600" source="#Embed('mainapp1.jpg')"/>
<s:TextInput id="titleCard" x="240" y="10" height="62" chromeColor="#515851" color="#060606"
contentBackgroundAlpha="1.0" contentBackgroundColor="#FFFFFF" text="Title"/>
<s:SkinnableContainer
id = "groupt" x="161" y="88" width="703" height="357" >
<s:TextArea id="mtext2" visible="false" x="0" y="0" width="703" height="357"
color="#000000" contentBackgroundAlpha="1.0"
contentBackgroundColor="#FFFFFF" editable="true" enabled="true"
paddingTop="70" text="Enter Text Here: (Side Two)" textAlign="center"/>
<s:TextArea id="mtext1" x="0" y="0" width="703" height="357" color="#030303"
contentBackgroundAlpha="1.0" contentBackgroundColor="#FFFFFF" editable="true"
enabled="true" fontFamily="Arial" fontStyle="normal" fontWeight="normal"
lineThrough="false" paddingTop="70" text="Enter Text Here: (Side One)"
textAlign="center" textDecoration="none" verticalAlign="middle"/>
</s:SkinnableContainer>
<s:Button x="763" y="10" height="62" label="Save" click="button2_clickHandler(event)"
cornerRadius="0" fontFamily="_sans"/>
<s:Label x="5" y="34" color="#49A6D6" fontFamily="Georgia" fontStyle="italic" fontWeight="bold"
paddingLeft="25" text="My"/>
<s:Label x="68" y="34" width="73" color="#E0B338" fontFamily="Georgia" fontStyle="italic"
fontWeight="bold" paddingLeft="0" text="Flash"/>
<s:Label x="138" y="34" color="#49A6D6" fontFamily="Georgia" fontStyle="italic" fontWeight="bold"
text="Cards!"/>
<s:Button id="flipButton" x="468" y="460" height="50" label="Flip" chromeColor="#2428D8"
click="button3_clickHandler(event)" fontFamily="_sans"/>
Part of my MyCards.mxml:
<?xml version="1.0" encoding="utf-8"?>
<fx:Script>
<![CDATA[
import flash.events.IOErrorEvent;
import flash.filesystem.File;
import flash.filesystem.FileMode;
import flash.filesystem.FileStream;
import mx.collections.ArrayCollection;
import mx.collections.ArrayList;
import mx.events.CollectionEvent;
import mx.events.FlexEvent;
import spark.effects.SlideViewTransition;
import spark.events.IndexChangeEvent;
import views.NewCard;
public var file:File;
public var fileStream:FileStream;
public var fileName:String = "Initial String";
private var directory:String = "SimpleSaveFromAIR";
public var nc:NewCard = new NewCard();
public var card:Object = new Object();
[Bindable]
public var cards:ArrayCollection = new ArrayCollection();
protected function button1_clickHandler(event:MouseEvent):void // pushed home button
{
var svt:SlideViewTransition = new SlideViewTransition(300, SlideViewTransition.SLIDE_RIGHT);
navigator.pushView(views.HomePage, event.relatedObject, svt);
}
public function add():void
{
var nc:NewCard = new NewCard();
var card:Object = new Object();
card.fTitle = nc.titleCard.text; //adding text to object from NewCard.mxml class
cards.addItem(card);
}
/* public function save():void
{
file = File.documentsDirectory.resolvePath(directory + "/" + fileName);
fileStream = new FileStream();
fileStream.open(file, FileMode.WRITE);
fileStream.writeObject(cards);
fileStream.close();
} */
public function myCardsList_creationCompleteHandler(event:FlexEvent):void
{
cards.addEventListener(CollectionEvent.COLLECTION_CHANGE, refreshList);
trace(cards.list); // no data at all shows up here
}
private function refreshList(event:CollectionEvent):void
{
trace("cards refreshed "+ cards.list);
}
public function testButton_clickHandler(event:MouseEvent):void
{
card.fTitle = nc.titleCard.text;
cards.addItem(card);
//trace(cards.list); // add data that has been added shows up here
}
]]>
</fx:Script>
<s:actionContent>
<s:Button id="testButton" label="Button" click="testButton_clickHandler(event)" />
<s:Button label="Delete"/>
<s:Button label="Home" click="button1_clickHandler(event)" skinClass="skins.homeButtonSkin"/>
</s:actionContent>
<s:Image x="0" y="-80" height="603" source="mainapp1.jpg"/>
<s:List id="myCardsList" x="10" y="10" left="0" right="0" top="0" bottom="0" width="1004"
height="500" dataProvider="{cards}" labelField="fTitle"
enabled="true" >
</s:List>
Again any help is greatly appreciated.
CardVO class:
package
{
public class CardVO
{
private var _title:String; //values returned from getter/setter functions
private var _side1:String;
private var _side2:String;
//get the "Title", "Side1" and "Side2" values from textAreas (later) and set them
// above variables
public function get Title():String {return _title;}
public function set Title(value:String):void { _title = value; }
public function get Side1():String {return _side1;}
public function set Side1(value:String):void {_side1 = value;}
public function get Side2():String {return _side2;}
public function set Side2(value:String):void {_side2 = value;}
}
}
** NewCard snippet:**
[Bindable]
public var myCard:CardVO = new CardVO(); // create new instance of CardVO
....
<!-- text property of mtext1 and mtext2 is bound and returned to the get/set functions in CardVO in the 'change' event-->
<!-- change sets setter values to those retrieved from textAreas-->
<s:TextArea id="mtext2" visible="false" x="0" y="0" width="703" height="357"
color="#000000" contentBackgroundAlpha="1.0"
contentBackgroundColor="#FFFFFF" editable="true" enabled="true"
paddingTop="70" text="{myCard.Side2}" change = "{myCard.Side2 = mtext2.text}"
textAlign="center"/>
<s:TextArea id="mtext1" x="0" y="0" width="703" height="357" color="#030303"
contentBackgroundAlpha="1.0" contentBackgroundColor="#FFFFFF" editable="true"
enabled="true" fontFamily="Arial" fontStyle="normal" fontWeight="normal"
lineThrough="false" paddingTop="70" text="{myCard.Side1}" change="{myCard.Side1 = mtext1.text}"
textAlign="center" textDecoration="none" verticalAlign="middle"/>
</s:SkinnableContainer>
MyCards snippet:
public function add():void
{
var nc:NewCard = new NewCard(); // create new instance of NewCard
cards.addItem(nc.myCard); // add new Item to ArrayCollection 'cards'
trace(cards.list);
}
Mycards List code
<s:List id="myCardsList" x="10" y="10" left="0" right="0" top="0" bottom="0" width="1004"
height="500" change="myCardsList_changeHandler(event)" dataProvider="{cards}"
enabled="true" >
<s:itemRenderer>
<fx:Component>
<s:MobileItemRenderer label="{data.title}"/>
</fx:Component>
</s:itemRenderer>
</s:List>
Assuming you're using the List component you should be able to specify the field you want to show using the labelField property.
<s:List id="myFlashCardList" dataProvider="{cards}" labelField="fTitle"/>
EDIT 2:
It seems like what you're trying to do here (and correct me if I'm wrong), is to have the user create a new instance of the NewCard object and then add it to your cards ArrayCollection. Your list then displays the titles of the cards the user has created.
Assuming this is the case, I think you're making it a little complicated than it needs to be. ArrayCollections can hold any type of class or object so you don't have to create a new Object and add it to the ArrayCollection every time they add a new card.
What I would do is create a Card class and populate it using your NewCard component. When you're done, you add that Card class to the ArrayCollection. Something like this:
The CardVO class:
package
{
public class CardVO
{
private var _title:String;
private var _side1:String;
private var _side2:String;
public function get Title():String { return _title; }
public function set Title(value:String):void { _title = value; }
public function get Side1():String { return _side1; }
public function set Side1(value:String):void { _side1 = value; }
public function get Side2():String { return _side2; }
public function set Side2(value:String):void { _side2 = value; }
}
}
Then in your NewCard.mxml file you use a CardVO to store the data:
<fx:Script>
<![CDATA[
...
[Bindable] public var myCard:CardVO = new CardVO();
...
]]>
</fx:Script>
<s:SkinnableContainer id = "groupt">
<s:TextArea id="mtext2" text="{myCard.Side2}" change="{myCard.Side2 = mtext2.text}"/>
<s:TextArea id="mtext1" text="{myCard.Side1}" change="{myCard.Side1 = mtext1.text}" />
</s:SkinnableContainer>
Then after the user has created their card, you pass the CardVO object to your ArrayCollection.
...
public function add():void
{
var nc:NewCard = new NewCard();
cards.addItem(nc.myCard);
}
...
This is a very abbreviated example so feel free to ask any questions that don't make sense. You should also look into Data Binding if you haven't already done so. It will save you a lot of time and make your apps more efficient once you get the hang of it. :)