【问题标题】:Flex Datagrid - how to obtain item for mouse x/y coordinates?Flex Datagrid - 如何获取鼠标 x/y 坐标的项目?
【发布时间】: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 不是一个选项。

【问题讨论】:

    标签: apache-flex flash actionscript-3 datagrid


    【解决方案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 Stackoverflow user http://stackoverflow.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】:

        dgdataGrid。 dg 的内容系统中行的顶部坐标(即从标题的底部开始)是:

        var topOfRow:int = ( int(dg.mouseY / dg.rowHeight) -1 ) * dg.rowHeight;
        

        您现在可以调整到其他坐标系: 以dg的系统为例:

        topOfRow += dh.headerHeight;
        

        或使用localToGlobal() 或其他。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2014-12-02
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2015-05-23
          • 1970-01-01
          • 1970-01-01
          • 2012-07-22
          相关资源
          最近更新 更多