I am trying to use ContextMenu() to display context menus in Flex 4.
Full Render code here http://pastebin.com/Kx8tJ1cY
The problem is that the context menu does not change when I add items to it.
Can anyone show me how to add a custom right click menu to a List box in flex (without using external JS, just using ContextMenu as Adobe intended.
Please and Thank you
Craig
I found the problem/solution. You cant use context menus if there are Vboxes or Tab Navigators. Which is insane because it means I cant do relative layout properly or decent variable width design.
Quoted from: http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/flash/ui/ContextMenu.html
For example, if a DataGrid control is a child of a TabNavigator or VBox container, the DataGrid control cannot have its own context menu.
Have you tried setting the contextMenu property of the List to you context menu? FlexExamples has a similar example posted for the DataGrid component. A List shouldn't be too different.
Something along these lines:
<?xml version="1.0" encoding="utf-8"?>
<!-- http://blog.flexexamples.com/2007/08/20/using-a-custom-context-menu-with-the-flex-datagrid-control/ -->
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
layout="vertical"
verticalAlign="middle"
backgroundColor="white"
creationComplete="init()">
<mx:Script>
<![CDATA[
import mx.controls.Alert;
[Bindable]
private var cm:ContextMenu;
private var alert:Alert;
private function init():void {
var cmi:ContextMenuItem = new ContextMenuItem("View item...", true);
cmi.addEventListener(ContextMenuEvent.MENU_ITEM_SELECT, contextMenuItem_menuItemSelect);
cm = new ContextMenu();
cm.hideBuiltInItems();
cm.customItems = [cmi];
cm.addEventListener(ContextMenuEvent.MENU_SELECT, contextMenu_menuSelect);
}
private function contextMenu_menuSelect(evt:ContextMenuEvent):void {
dataGrid.selectedIndex = lastRollOverIndex;
}
private function contextMenuItem_menuItemSelect(evt:ContextMenuEvent):void {
var obj:Object = dataGrid.selectedItem;
alert = Alert.show("Property A: " + obj.#propertyA + "\\n" + "Property B: " + obj.#propertyB, obj.#label, Alert.OK);
}
]]>
</mx:Script>
<mx:XML id="itemsXML">
<items>
<item label="Item 1" data="i001" propertyA="Item 1.A" propertyB="Item 1.B" />
<item label="Item 2" data="i002" propertyA="Item 2.A" propertyB="Item 2.B" />
<item label="Item 3" data="i003" propertyA="Item 3.A" propertyB="Item 3.B" />
<item label="Item 4" data="i004" propertyA="Item 4.A" propertyB="Item 4.B" />
<item label="Item 5" data="i005" propertyA="Item 5.A" propertyB="Item 5.B" />
<item label="Item 6" data="i006" propertyA="Item 6.A" propertyB="Item 6.B" />
<item label="Item 7" data="i007" propertyA="Item 7.A" propertyB="Item 7.B" />
<item label="Item 8" data="i008" propertyA="Item 8.A" propertyB="Item 8.B" />
</items>
</mx:XML>
<mx:Number id="lastRollOverIndex" />
<mx:DataGrid id="dataGrid"
width="400"
dataProvider="{itemsXML.item}"
contextMenu="{cm}"
itemRollOver="lastRollOverIndex = event.rowIndex">
<mx:columns>
<mx:DataGridColumn id="labelCol"
dataField="#label"
headerText="Label:" />
<mx:DataGridColumn id="propACol"
dataField="#propertyA"
headerText="Property A:" />
<mx:DataGridColumn id="propBCol"
dataField="#propertyB"
headerText="Property B:" />
</mx:columns>
</mx:DataGrid>
<mx:Label text="{dataGrid.selectedItem.#label}" />
</mx:Application>
Related
New with Flex and mxml. How I can bind AS3 class' function to a menubar item? My menubar code is this:
<mx:MenuBar id="myMenubar" labelField="#label">
<fx:XMLList xmlns="">
<item label="File">
<item label="New" />
<item label="Open"/>
<item label="Save"/>
<item label="Save As"/>
<item label="Quit"/>
</item>
<item label="Edit">
<item label="Undo"/>
<item label="Redo"/>
<item label="Preferences"/>
</item>
<item label="Level">
<item label="New Room"/>
<item label="Properties"/>
</item>
<item label="Objects">
<item label="Clickable"/>
<item label="Character"/>
<item label="Door"/>
<item label="Treasure"/>
</item>
</fx:XMLList>
</mx:MenuBar>
I looked through few examples in Google but couldn't find definite explanation or example how to trigger AS3 class functions. I presume that I should somehow make click event listener for my subitems and make a call to my class. However, mxml syntax confuses me.
MXML is just a way to describe data and components declaratively, in the end it's compiled to pure ActionScript anyways, so you can simply subscribe an appropriate listener to myMenubar.
I think you are looking for the itemClick event:
myMenubar.addEventListener(MenuEvent.ITEM_CLICK, function(e:MenuEvent):void
{
trace(e.label + ' was clicked');
});
In order to be able to distinguish the items while being able to change the lablels, i'd recommend to assign IDs to them:
<mx:MenuBar id="myMenubar" labelField="#label">
<fx:XMLList xmlns="">
<item label="File">
<item id="abc" label="New" />
<item id="xyz" label="Open"/>
...
Then you could for example use a simple switch to handle the different items:
myMenubar.addEventListener(MenuEvent.ITEM_CLICK, function(e:MenuEvent):void
{
switch(e.item.#id)
{
case 'abc':
// do something
break;
case 'xyz':
// do something else
break;
}
});
Ofcourse you could also define which function to call using MXML:
<mx:MenuBar id="myMenubar" labelField="#label" itemClick="myMenuItemClickHandler(event)">
-
private function myMenuItemClickHandler(e:MenuEvent)
{
...
}
See also the example in the Adobe LiveDocs to get a grasp on how this all comes together:
<?xml version="1.0" encoding="utf-8"?>
<!-- Simple example to demonstrate the Halo MenuBar control. -->
<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"
initialize="initCollections();">
<fx:Script>
<![CDATA[
import mx.collections.*;
import mx.controls.Alert;
import mx.events.MenuEvent;
[Bindable]
public var menuBarCollection:XMLListCollection;
private var menubarXML:XMLList =
<>
<menuitem label="Menu1" data="top">
<menuitem label="MenuItem 1-A" data="1A"/>
<menuitem label="MenuItem 1-B" data="1B"/>
</menuitem>
<menuitem label="Menu2" data="top">
<menuitem label="MenuItem 2-A" type="check" data="2A"/>
<menuitem type="separator"/>
<menuitem label="MenuItem 2-B" >
<menuitem label="SubMenuItem 3-A" type="radio"
groupName="one" data="3A"/>
<menuitem label="SubMenuItem 3-B" type="radio"
groupName="one" data="3B"/>
</menuitem>
</menuitem>
</>;
// Event handler to initialize the MenuBar control.
private function initCollections():void {
menuBarCollection = new XMLListCollection(menubarXML);
}
// Event handler for the MenuBar control's itemClick event.
private function menuHandler(evt:MenuEvent):void {
// Don't open the Alert for a menu bar item that
// opens a popup submenu.
if (evt.item.#data != "top") {
Alert.show("Label: " + evt.item.#label + "\n" +
"Data: " + evt.item.#data, "Clicked menu item");
}
}
]]>
</fx:Script>
<s:Panel title="Halo MenuBar Control Example"
width="75%" height="75%"
horizontalCenter="0" verticalCenter="0">
<s:VGroup left="10" right="10" top="10" bottom="10">
<s:Label width="100%" color="blue" text="Select a menu item."/>
<mx:MenuBar labelField="#label" itemClick="menuHandler(event);"
dataProvider="{menuBarCollection}" />
</s:VGroup>
</s:Panel>
</s:Application>
I have one problem related to charts.
I have Column chart with 1000+ columns on it with the scroll bar on it. Now I want to save it as Image to my Disktop or any location without scroll.
ScrollableAxisRenderer Class I have Downloaded from one of the link please find it below: -
http://www.connectedpixel.com/blog/scrollingcharts
Sample Column Chart Example: -
<?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"
creationComplete="init();" xmlns:charts="com.connectedpixel.charts.*">
<fx:Declarations>
<fx:XML xmlns="" id="myData">
<items>
<item year="1960" rain="92" />
<item year="1961" rain="192" />
<item year="1962" rain="32" />
<item year="1963" rain="52" />
<item year="1964" rain="112" />
<item year="1965" rain="52" />
<item year="1966" rain="88" />
<item year="1967" rain="52" />
<item year="1968" rain="66" />
<item year="1969" rain="39" />
<item year="1970" rain="192" />
<item year="1971" rain="182" />
<item year="1972" rain="177" />
<item year="1973" rain="179" />
<item year="1974" rain="198" />
<item year="1975" rain="207" />
<item year="1976" rain="388" />
<item year="1977" rain="372" />
<item year="1978" rain="352" />
</items>
</fx:XML>
<s:XMLListCollection id="rainData" source="{myData.children()}" />
</fx:Declarations>
<fx:Script>
<![CDATA[
import mx.graphics.ImageSnapshot;
import mx.graphics.codec.PNGEncoder;
protected function initCreationComp():void
{
var image:ImageSnapshot = ImageSnapshot.captureImage(myChart,300,new PNGEncoder(),true);
var file:FileReference = new FileReference();
var chartName:String = "myChart"+count+".png";
file.save(image.data, chartName);
}
]]>
</fx:Script>
<mx:VBox width="100%" height="100%" x="50" y="50">
<s:Button label="Download Image" click="initCreationComp()"/>
<mx:ColumnChart id="myChart" name="myChart"
width="80%" height="80%"
dataProvider="{myData.children()}"
showDataTips="true" maxColumnWidth="35">
<mx:horizontalAxis>
<mx:CategoryAxis id="yearAxis" categoryField="#year" />
</mx:horizontalAxis>
<mx:series>
<mx:ColumnSeries xField="#year" yField="#rain" displayName="Rain" />
</mx:series>
<mx:horizontalAxisRenderers>
<charts:ScrollableAxisRenderer id="scrollAxisRenderer" axis="{yearAxis}" tickPlacement="none"
placement="bottom" labelGap="3" maxVisibleColumns="4"/>
</mx:horizontalAxisRenderers>
</mx:ColumnChart>
</mx:VBox>
</s:Application>
Thanks in advance....
Put the chart inside container which will show scrollbars instead of your chart:
<mx:VBox width="100%" height="100%" x="50" y="50">
<s:Button label="Download Image" click="initCreationComp()"/>
<mx:VBox width="80%" height="80%"
minWidth="100" minHeight="100">
<mx:ColumnChart id="myChart" name="myChart"
dataProvider="{myData.children()}"
showDataTips="true" maxColumnWidth="35">
<!-- etc -->
</mx:ColumnChart>
</mx:VBox>
</mx:VBox>
I have an ItemRenderer that is shared by several applications (inside a DataGrid), and I would like to add a context menu to it (rather than in each application). The renderer is derived from the Canvas class, and the code to create the context menu looks something like:
var menuItem:ContextMenuItem = new ContextMenuItem("Test");
menuItem.addEventListener(ContextMenuEvent.MENU_ITEM_SELECT, contextCallback);
var customContextMenu:ContextMenu = new ContextMenu();
customContextMenu.hideBuiltInItems(); //hide flash menu
customContextMenu.customItems.push(menuItem);
this.contextMenu = customContextMenu;
However, when I right click on the cell in the datagrid, I get the default Flash Context Menu. Is this not possible?
Edit: Here is a fully runnable example, which doesn't show the context menu's:
Application.mxml:
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
layout="vertical"
verticalAlign="middle"
backgroundColor="white">
<mx:Model id="items">
<items>
<item label="Item 1" data="i001" propertyA="Item 1.A" propertyB="Item 1.B" />
<item label="Item 2" data="i002" propertyA="Item 2.A" propertyB="Item 2.B" />
<item label="Item 3" data="i003" propertyA="Item 3.A" propertyB="Item 3.B" />
<item label="Item 4" data="i004" propertyA="Item 4.A" propertyB="Item 4.B" />
<item label="Item 5" data="i005" propertyA="Item 5.A" propertyB="Item 5.B" />
<item label="Item 6" data="i006" propertyA="Item 6.A" propertyB="Item 6.B" />
<item label="Item 7" data="i007" propertyA="Item 7.A" propertyB="Item 7.B" />
<item label="Item 8" data="i008" propertyA="Item 8.A" propertyB="Item 8.B" />
</items>
</mx:Model>
<mx:DataGrid id="dataGrid" width="400" dataProvider="{items.item}">
<mx:columns>
<mx:DataGridColumn headerText="No Menu" dataField="label" />
<mx:DataGridColumn headerText="Menu" dataField="propertyA" itemRenderer="canvasRenderer"/>
</mx:columns>
</mx:DataGrid>
canvasRenderer.mxml:
<mx:Canvas xmlns:mx="http://www.adobe.com/2006/mxml" width="100%" verticalScrollPolicy="off" horizontalScrollPolicy="off" resize="this.setSize()" creationComplete="init()" implements="mx.controls.listClasses.IDropInListItemRenderer">
<mx:Script>
<![CDATA[
import mx.controls.listClasses.ListData;
import mx.controls.dataGridClasses.DataGridListData;
import mx.controls.listClasses.BaseListData;
import mx.events.FlexEvent;
private var _listData:DataGridListData;
private function init():void {
var menuItem:ContextMenuItem = new ContextMenuItem("Copy", true);
menuItem.addEventListener(ContextMenuEvent.MENU_ITEM_SELECT, function():void {
trace("selected");
});
var menu:ContextMenu = new ContextMenu();
menu.hideBuiltInItems(); //hide flash menu
menu.customItems.push(menuItem);
this.contextMenu = menu;
}
public override function set data(value:Object):void {
super.data = value;
if(_listData && myLabel) {
var text:String = _listData.label ? _listData.label : value[_listData.dataField];
myLabel.text = text;
myLabel.toolTip = text;
}
}
public function get listData():BaseListData { return _listData; }
public function set listData(value:BaseListData):void { _listData = DataGridListData(value); }
public function setSize():void { myLabel.width = this.width; }
]]>
</mx:Script>
<mx:Label id="myLabel" truncateToFit="true"/>
This works:
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
layout="vertical"
verticalAlign="middle"
backgroundColor="white"
creationComplete="init()">
<mx:Script>
<![CDATA[
import mx.controls.Alert;
[Bindable] public var cm1:ContextMenu;
[Bindable] public var cm2:ContextMenu;
private function init():void {
var cmi1:ContextMenuItem = new ContextMenuItem("View item in column 1...", true);
cmi1.addEventListener(ContextMenuEvent.MENU_ITEM_SELECT, contextMenuItem_menuItemSelect);
cm1 = new ContextMenu();
cm1.hideBuiltInItems();
cm1.customItems = [cmi1];
cm1.addEventListener(ContextMenuEvent.MENU_SELECT, contextMenu_menuSelect);
var cmi2:ContextMenuItem = new ContextMenuItem("View item in column 2...", true);
cmi2.addEventListener(ContextMenuEvent.MENU_ITEM_SELECT, contextMenuItem_menuItemSelect);
cm2 = new ContextMenu();
cm2.hideBuiltInItems();
cm2.customItems = [cmi2];
cm2.addEventListener(ContextMenuEvent.MENU_SELECT, contextMenu_menuSelect);
}
private function contextMenu_menuSelect(evt:ContextMenuEvent):void {
dataGrid.selectedIndex = lastRollOverIndex;
}
private function contextMenuItem_menuItemSelect(evt:ContextMenuEvent):void {
var obj:Object = dataGrid.selectedItem;
Alert.show("Property A: " + obj.propertyA + "\n" + "Property B: " + obj.propertyB, obj.label, Alert.OK);
}
]]>
</mx:Script>
<mx:Model id="items">
<items>
<item label="Item 1" data="i001" propertyA="Item 1.A" propertyB="Item 1.B" />
<item label="Item 2" data="i002" propertyA="Item 2.A" propertyB="Item 2.B" />
<item label="Item 3" data="i003" propertyA="Item 3.A" propertyB="Item 3.B" />
<item label="Item 4" data="i004" propertyA="Item 4.A" propertyB="Item 4.B" />
<item label="Item 5" data="i005" propertyA="Item 5.A" propertyB="Item 5.B" />
<item label="Item 6" data="i006" propertyA="Item 6.A" propertyB="Item 6.B" />
<item label="Item 7" data="i007" propertyA="Item 7.A" propertyB="Item 7.B" />
<item label="Item 8" data="i008" propertyA="Item 8.A" propertyB="Item 8.B" />
</items>
</mx:Model>
<mx:Number id="lastRollOverIndex" />
<mx:DataGrid id="dataGrid" width="400" dataProvider="{items.item}">
<mx:columns>
<mx:DataGridColumn headerText="Label">
<mx:itemRenderer>
<mx:Component>
<mx:Label text="{data.label}" contextMenu="{outerDocument.cm1}"/>
</mx:Component>
</mx:itemRenderer>
</mx:DataGridColumn>
<mx:DataGridColumn headerText="Property A">
<mx:itemRenderer>
<mx:Component>
<mx:Label text="{data.propertyA}" contextMenu="{outerDocument.cm2}"/>
</mx:Component>
</mx:itemRenderer>
</mx:DataGridColumn>
</mx:columns>
</mx:DataGrid>
<mx:Label text="{dataGrid.selectedItem.label}" />
</mx:Application>
I've added the context menu to an itemRenderer in a List with the Flextras DataSorter. However, I don't see any difference between what I did and what you're doing.
Source code here:
http://www.flextras.com/DataSorter/Samples/RightClick/srcview/index.html
and the running Sample
http://www.flextras.com/DataSorter/Samples/RightClick/
Can you share more code? What is the "this" that you're adding the context menu too? Is your temRenderer in-line or a separate component?
I want to have the title of my application to be freezed, that is, even if I scroll down the page, I want the label name to be in focus, at the top always.. Is that possible?
Now if I scroll down , the screen name disappears. Instead, can it be freezed like freezing columns or rows in excel?
Run this:
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" width="100%" height="100%">
<mx:VBox width="100%" height="100%">
<mx:Label text="My Label!" />
<mx:VBox width="100%" height="100%" minWidth="0" minHeight="0">
<mx:CheckBox label="1" />
<mx:CheckBox label="2" />
<mx:CheckBox label="3" />
<mx:CheckBox label="4" />
<mx:CheckBox label="5" />
<mx:CheckBox label="6" />
<mx:CheckBox label="7" />
<mx:CheckBox label="8" />
<mx:CheckBox label="9" />
<mx:CheckBox label="10" />
<mx:CheckBox label="11" />
<mx:CheckBox label="12" />
<mx:CheckBox label="13" />
<mx:CheckBox label="14" />
<mx:CheckBox label="15" />
<mx:CheckBox label="16" />
<mx:CheckBox label="17" />
<mx:CheckBox label="18" />
<mx:CheckBox label="19" />
</mx:VBox>
<mx:Label text="Bottom label here!" />
</mx:VBox>
</mx:Application>
Set minWidth=0 and minHeight=0 so Vbox is not going to expand.
Have you tried ApplicationControlBar - use it with dock set to true.
Quoting from the linked page:
Docked mode: The bar is always at the top of the application's drawing area and becomes part of the application chrome. Any application-level scroll bars don't apply to the component, so that it always remains at the top of the visible area, and the bar expands to fill the width of the application. To create a docked bar, set the value of the dock property to true.
I don't know if I understand you correct, but I would make it the following way:
<mx:VBox width="100%" height="100%" verticalScrollPolicy="off">
<mx:Label label="My Title" />
<mx:VBox name="content">
...
</mx:VBox>
</mx:VBox>
So you'll be scrolling just the second VBox and the outer VBox with the title keeps always on top.
<mx:Script>
<![CDATA[
private function openAllNodes():void {
tree.openItems = dp..node;
}
private function closeAllNodes():void {
tree.openItems = [];
}
]]>
</mx:Script>
<mx:XML id="dp">
<root>
<node label="Parent 1">
<node label="Child 1" />
<node label="Child 2">
<node label="Grandchild 1" />
<node label="Grandchild 2" />
</node>
<node label="Child 3" />
<node label="Child 4" />
</node>
</root>
</mx:XML>
<mx:ApplicationControlBar dock="true">
<mx:Button label="Open all nodes" click="openAllNodes();" />
<mx:Button label="Close all nodes" click="closeAllNodes();" />
</mx:ApplicationControlBar>
<mx:Tree id="tree"
dataProvider="{dp}"
showRoot="false"
labelField="#label"
width="200" />
Unless or other wise i click my parent list, the child or the next list must be in a disabled state.
I click on Child 1, then only Child 2 Must be able to select.
Please Help Me.
It sounds like you might want to extend the tree class and override some of the methods to implement your special functionality. Look at overriding the drawItem, mouseClickHandler, and possibly the expandItem functions.