Flex Datagrid - 如何获取鼠标 x/y 坐标的项目?
Posted
技术标签:
【中文标题】Flex Datagrid - 如何获取鼠标 x/y 坐标的项目?【英文标题】:Flex Datagrid - how to obtain item for mouse x/y coordinates? 【发布时间】:2010-12-19 21:10:30 【问题描述】:我的任务是在 DataGrid 实例中选择一个项目,除了屏幕上的坐标之外什么都没有。
我们正在我们的 Flash 应用程序中实现右键单击功能,目标是能够右键单击 DG 行,这将选择该行并显示一个包含一些上下文命令的弹出窗口。
在this site 的帮助下,我设法将右键单击事件添加到我的 Flex 应用程序中。
到目前为止,进一步的进展是通过
获取DataGrid实例var objects : Array = this.getObjectsUnderPoint(new Point(this.mouseX, this.mouseY));
然后调查数组的每个项目,因为其中一个“parent.parentList”指的是 DataGrid 实例。
现在我被困住了——我找不到任何点对项转换器功能或任何东西。到目前为止,任何关于我的方法的 cmet 都非常受欢迎!
谢谢!
PS:不幸的是,使用标准 Flash ContextMenu 不是一个选项。
【问题讨论】:
【参考方案1】:/**
* Let mx and my be the mouse coordinates
* (relative to the stage, not relative to the clicked object)
* */
var len:Number = dg.dataProvider.length;
var i:Number;
var p1:Point;
var p2:Point;
var renderer:DisplayObject;
for(i = 0; i < len; i++)
renderer = DisplayObject(dg.indexToItemRenderer(i));
if(!renderer)//item is not displayed (scroll to view it)
continue;
p1 = new Point(renderer.x, renderer.y);
p2 = new Point(renderer.width, renderer.height);
p1 = renderer.parent.localToGlobal(p1);
p2 = renderer.localToGlobal(p2);
if(mx >= p1.x && mx <= p2.x && my >= p1.y && my <= p2.y)
trace("You clicked on " + dg.dataProvider.getItemAt(i));
break;
您可以将ContextMenu 附加到DataGrid 的itemRenderer
,这样您就可以从事件的currentTarget
属性中获取右键单击的项目。尽可能简单。
【讨论】:
不,不幸的是它不是。使用标准的 Flex ContextMenu 不是一个选项,所以回到第一个问题:“我的任务是在 DataGrid 实例中选择一个项目,除了屏幕上的坐标之外什么都没有。” 如果你可以使用items-under-point函数获取datagrid,你应该也可以获取item renderer。 太棒了,就像一个魅力!我添加了完整代码的答案,见下文。谢谢老兄。【参考方案2】:您可以使用itemRollOver 事件(以及相关的 itemRollOut)来跟踪鼠标经过的最新项目。只需将项目保存在变量中即可。当您显示上下文菜单时,您可以直接使用保存的项目,而不是尝试根据 (x,y) 坐标找到它。
【讨论】:
【参考方案3】:这是 Flash 方面的完整 AS3 代码。请注意,您还需要在嵌入的 html 中使用 javascript 才能使其正常工作。
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="horizontal"
minWidth="1024" minHeight="768"
creationComplete="onAppCreationComplete()"
click="onRightClick()"
>
<mx:DataGrid
id="dgTest"
dataProvider="['aaa','bbbbbbbbbbbbbbb']"
>
<mx:columns>
<mx:DataGridColumn />
</mx:columns>
</mx:DataGrid>
<mx:Script>
<![CDATA[
import mx.binding.utils.BindingUtils;
import mx.controls.Alert;
import mx.controls.Menu;
import mx.effects.Fade;
import mx.events.MenuEvent;
[Bindable]
public var customContextMenuItem : Object;
public var customContextMenu : Menu;
protected function onAppCreationComplete () : void
ExternalInterface.addCallback("rightClick", onRightClick);
this.customContextMenu = this.createCustomContextMenu();
protected function onRightClick () : void
// find datagrid at mouse click coords
var dg : DataGrid = this.getDataGridFromObjectsUnderPoint(this.mouseX, this.mouseY);
if (dg)
// if any, find clicked item
this.customContextMenuItem = this.findClickedItem(this.mouseX, this.mouseY, dg);
if (this.customContextMenuItem)
// right clicking an item with the menu already showing does not show a new menu
// unless the previous one is hidden first
this.customContextMenu.hide();
this.customContextMenu.show(this.mouseX+3, this.mouseY+2);
protected function getDataGridFromObjectsUnderPoint (x:Number, y:Number) : DataGrid
var objectsHere : Array = this.getObjectsUnderPoint(new Point(this.mouseX, this.mouseY));
for each (var dispObj:DisplayObject in objectsHere)
while (dispObj)
if (dispObj is DataGrid)
return dispObj as DataGrid;
dispObj = dispObj.parent;
return null;
/**
* Returns a dataProvider item that displays at the given coords for the given dataGrid.
* Code provided by *** user http://***.com/users/165297/amarghosh,
* thanks a lot!
*/
protected function findClickedItem (x:Number, y:Number, dg:DataGrid) : Object
var p1 : Point;
var p2 : Point;
var renderer : DisplayObject;
for(var i:int=0; i<dg.dataProvider.length; i++)
renderer = DisplayObject(dg.indexToItemRenderer(i));
if (!renderer) //item is not displayed (scroll to view it)
continue;
p1 = new Point(renderer.x, renderer.y);
p2 = new Point(renderer.width, renderer.height);
p1 = renderer.parent.localToGlobal(p1);
p2 = renderer.localToGlobal(p2);
if(x >= p1.x && x <= p2.x && y >= p1.y && y <= p2.y)
return dg.dataProvider.getItemAt(i);
return null;
protected function createCustomContextMenu () : Menu
// create a dynamic-object as our first menu item entry, and use data binding
// to dynamically populate the 'title' value whenever our right-clicked item
// has changed
var menuItem : Object = new Object();
menuItem.title = "default";
BindingUtils.bindSetter(function (item:Object) : void
trace(item);
menuItem.title = "Edit '" + item + "'";
, this, ["customContextMenuItem"]);
var dataProvider : Array = [ menuItem, title:"Exit" ];
// create a nicely styled menu that looks very different to the standard Flash menu
var menu : Menu = Menu.createMenu(this, dataProvider, false);
menu.setStyle("fontWeight", "bold");
menu.setStyle("backgroundColor", 0x000000); // standard back/foreground
menu.setStyle("color", 0xf0f0f0);
menu.setStyle("rollOverColor", 0x444444); // mouse hover back/foreground
menu.setStyle("textRollOverColor", 0xffffff);
menu.setStyle("selectionColor", 0x444444); // mouse click back/foreground
menu.setStyle("textSelectedColor", 0xe18c31);
menu.setStyle("openDuration", 0);
menu.labelField = "title";
// we want to react to clicks in the menu
menu.addEventListener(MenuEvent.ITEM_CLICK, function (event:MenuEvent) : void
Alert.show("Menu item clicked - clicked item title '" + event.item.title + "'");
);
// done
return menu;
]]>
</mx:Script>
</mx:Application>
【讨论】:
【参考方案4】:dg
是dataGrid
。
dg 的内容系统中行的顶部坐标(即从标题的底部开始)是:
var topOfRow:int = ( int(dg.mouseY / dg.rowHeight) -1 ) * dg.rowHeight;
您现在可以调整到其他坐标系: 以dg的系统为例:
topOfRow += dh.headerHeight;
或使用localToGlobal()
或其他。
【讨论】:
以上是关于Flex Datagrid - 如何获取鼠标 x/y 坐标的项目?的主要内容,如果未能解决你的问题,请参考以下文章
如何在 Adobe Flex 中合并 DataGrid/Advanced DataGrid 中的单元格
Flex 3:如何在其 ItemRenderer 中获取 DataGridColumn 的 dataField?