【发布时间】:2012-02-23 06:34:50
【问题描述】:
首先对这个非常冗长的问题表示抱歉。我正在尝试使用火花DataGrid 实现Org.Chart。 Org.Chart 的数据没有改变,因此我对这些值进行了硬编码。我必须实现这个Org.Chart,因为我需要浮动Nodes,并且与使用外部组件相比,连接线的绘制应该有点不同。请找到我试图实现的以下图像:
这是一个想法:
DataGrid 的每个单元格都可以是connecting lines 或actor。我有一个自定义组件MyOrgChartNode,它有两种状态:chartLinesState 和chartActorState。此组件用作ItemRenderer 的DataGrid。这是MyOrgChartNode的代码:
<fx:Script>
<![CDATA[
import mx.controls.Alert;
import scripts.valueObjects.ActorVO;
import scripts.valueObjects.CellRendererVO;
[Bindable]
private var _cellRenderer:CellRendererVO;
[Bindable]
private var _lineColor:uint = 0xFF0000;
[Bindable]
private var _lineWidth:int = 1;
override public function prepare(hasBeenRecycled:Boolean):void
{
if (data != null)
{
this.height = parseInt(data['cellHeight']);
if (columnIndex == 1 || columnIndex == 3)
{
this.width = 50;
}
currentState = (data[column.dataField] as CellRendererVO).stateName;
}
}
protected function orgChartNode_clickHandler(event:MouseEvent):void
{
// TODO Auto-generated method stub
}
]]>
</fx:Script>
<s:states>
<s:State name="chartLinesState" />
<s:State name="chartActorState" />
</s:states>
<s:VGroup width="100%" height="100%" includeIn="chartActorState">
<myOrgChart:OrgChartNode id="orgChartNode" width="100%" height="100%" click="orgChartNode_clickHandler(event)"
nodeActor="{(data[column.dataField] as CellRendererVO).nodeActor}" />
</s:VGroup>
<s:VGroup width="100%" height="100%" includeIn="chartLinesState">
<s:HGroup width="100%" height="100%"
gap="0" horizontalAlign="center" verticalAlign="middle">
<s:VGroup id="horizontalLeftLine" height="100%" width="100%"
horizontalAlign="center" verticalAlign="middle"
visible="{(data[column.dataField] as CellRendererVO).hasHorizontalLeftLine}">
<mx:HRule width="100%" strokeWidth="{_lineWidth}" strokeColor="{_lineColor}"
opaqueBackground="{_lineColor}"/>
</s:VGroup>
<s:VGroup height="100%" gap="0" horizontalAlign="center"
verticalAlign="middle"
includeInLayout="{(data[column.dataField] as CellRendererVO).hasVerticalTopLine || (data[column.dataField] as CellRendererVO).hasVerticalBottomLine}">
<s:VGroup id="verticalTopLine" height="50%" verticalAlign="middle"
visible="{(data[column.dataField] as CellRendererVO).hasVerticalTopLine}">
<mx:VRule height="100%" strokeWidth="{_lineWidth}" strokeColor="{_lineColor}"
opaqueBackground="{_lineColor}"/>
</s:VGroup>
<s:VGroup id="verticalBottomLine" height="50%" verticalAlign="middle"
visible="{(data[column.dataField] as CellRendererVO).hasVerticalBottomLine}">
<mx:VRule height="100%" strokeWidth="{_lineWidth}" strokeColor="{_lineColor}"
opaqueBackground="{_lineColor}"/>
</s:VGroup>
</s:VGroup>
<s:VGroup id="horizontalRightLine" height="100%" width="100%"
horizontalAlign="center" verticalAlign="middle"
visible="{(data[column.dataField] as CellRendererVO).hasHorizontalRightLine}">
<mx:HRule width="100%" strokeWidth="{_lineWidth}" strokeColor="{_lineColor}"
opaqueBackground="{_lineColor}"/>
</s:VGroup>
</s:HGroup>
</s:VGroup>
在上面的代码中,我使用了valueObjectCellRendererVO,其中包含显示单元格所需的信息,例如不同HRules 和VRule 存在的可见性。 CellRendererVO 的代码在这里:
package scripts.valueObjects
{
public class CellRendererVO extends Object
{
private var _hasVerticalTopLine:Boolean;
private var _hasVerticalBottomLine:Boolean;
private var _hasHorizontalLeftLine:Boolean;
private var _hasHorizontalRightLine:Boolean;
private var _nodeActor:ActorVO;
private var _stateName:String;
public function CellRendererVO(hasVerticalTopLine:Boolean = false, hasVerticalBottomLine:Boolean = false,
hasHorizontalLeftLine:Boolean = false, hasHorizontalRightLine:Boolean = false,
nodeActor:ActorVO = null, stateName:String = "chartLinesState"
)
{
this.hasVerticalTopLine = hasVerticalTopLine;
this.hasVerticalBottomLine = hasVerticalBottomLine;
this.hasHorizontalLeftLine = hasHorizontalLeftLine;
this.hasHorizontalRightLine = hasHorizontalRightLine;
this.nodeActor = nodeActor;
this.stateName = stateName;
}
public function get hasVerticalTopLine():Boolean
{
return _hasVerticalTopLine;
}
public function set hasVerticalTopLine(value:Boolean):void
{
_hasVerticalTopLine = value;
}
public function get hasVerticalBottomLine():Boolean
{
return _hasVerticalBottomLine;
}
public function set hasVerticalBottomLine(value:Boolean):void
{
_hasVerticalBottomLine = value;
}
public function get hasHorizontalLeftLine():Boolean
{
return _hasHorizontalLeftLine;
}
public function set hasHorizontalLeftLine(value:Boolean):void
{
_hasHorizontalLeftLine = value;
}
public function get hasHorizontalRightLine():Boolean
{
return _hasHorizontalRightLine;
}
public function set hasHorizontalRightLine(value:Boolean):void
{
_hasHorizontalRightLine = value;
}
public function get nodeActor():ActorVO
{
return _nodeActor;
}
public function set nodeActor(value:ActorVO):void
{
_nodeActor = value;
}
public function get stateName():String
{
return _stateName;
}
public function set stateName(value:String):void
{
_stateName = value;
}
}
}
如您所见,有不同的布尔变量用于获取连接线,还有另一个 valueObject ActorVO 具有 actor 数据。代码如下:
package scripts.valueObjects
{
public class ActorVO extends Object
{
private var _id:int;
private var _fullName:String;
private var _imageSource:String;
private var _beta1:Number;
private var _beta2:Number;
private var _beta3:Number;
private var _nationality:String;
private var _education:String;
private var _gender:String;
private var _displayName:String;
private var _progress:Number;
private var _showImage:Boolean;
public function ActorVO(id:int = -1, fullName:String = "Full Name", imageSource:String = "",
beta1:Number = -1, beta2:Number = -1, beta3:Number = -1, nationality:String = "India",
gender:String = "M", progress:Number = 10, education:String = "", showImage:Boolean = true)
{
this.id = id;
this.fullName = fullName;
this.imageSource = imageSource;
this.beta1 = beta1;
this.beta2 = beta2;
this.beta3 = beta3;
this.nationality = nationality;
this.gender = gender;
this.progress = progress;
this.education = education;
this.showImage = showImage;
}
public function copyData(actor:ActorVO):void
{
this.id = actor.id;
this.fullName = actor.fullName;
this.imageSource = actor.imageSource;
this.beta1 = actor.beta1;
this.beta2 = actor.beta2;
this.beta3 = actor.beta3;
this.nationality = actor.nationality;
this.gender = actor.gender;
this.progress = actor.progress;
this.education = actor.education;
this.showImage = showImage
}
public function get id():int
{
return _id;
}
public function set id(value:int):void
{
_id = value;
}
public function get fullName():String
{
return _fullName;
}
public function set fullName(value:String):void
{
_fullName = value;
displayName = value.substring(value.lastIndexOf(" ") + 1); //return the last name in the string
}
public function get imageSource():String
{
return _imageSource;
}
public function set imageSource(value:String):void
{
/**
* When copyData function is used, value is ./assets/images/people/
* and hence imageSouce will be prepended with ./assets/images/people
* hence first check if there exists path
* */
_imageSource = "./assets/images/people/" + value;
if (value.indexOf("./") != -1)
{
_imageSource = value;
}
}
public function get beta1():Number
{
return _beta1;
}
public function set beta1(value:Number):void
{
_beta1 = value;
}
public function get beta2():Number
{
return _beta2;
}
public function set beta2(value:Number):void
{
_beta2 = value;
}
public function get beta3():Number
{
return _beta3;
}
public function set beta3(value:Number):void
{
_beta3 = value;
}
public function get nationality():String
{
return _nationality;
}
public function set nationality(value:String):void
{
_nationality = value;
}
public function get education():String
{
return _education;
}
public function set education(value:String):void
{
_education = value;
}
public function get gender():String
{
return _gender;
}
public function set gender(value:String):void
{
_gender = value;
}
public function get displayName():String
{
return _displayName;
}
public function set displayName(value:String):void
{
_displayName = value;
}
public function get progress():Number
{
return _progress;
}
public function set progress(value:Number):void
{
_progress = value;
}
public function get showImage():Boolean
{
return _showImage;
}
public function set showImage(value:Boolean):void
{
_showImage = value;
}
}
}
这是来自Application 的DataGrid 代码:
<s:DataGrid id="orgChartDG" borderVisible="false" skinClass="skins.OrgChartDataGridSkin"
dataProvider="{orgChartDP}" variableRowHeight="true">
<s:columns>
<s:ArrayList>
<s:GridColumn dataField="col1" itemRenderer="customComponents.myOrgChart.TestIR" />
<s:GridColumn dataField="col2" itemRenderer="customComponents.myOrgChart.TestIR" />
<s:GridColumn dataField="col3" itemRenderer="customComponents.myOrgChart.TestIR" />
<s:GridColumn dataField="col4" itemRenderer="customComponents.myOrgChart.TestIR" />
<s:GridColumn dataField="col5" itemRenderer="customComponents.myOrgChart.TestIR" />
<s:GridColumn dataField="col6" itemRenderer="customComponents.myOrgChart.TestIR" />
<s:GridColumn dataField="col7" itemRenderer="customComponents.myOrgChart.TestIR" />
<s:GridColumn dataField="col8" itemRenderer="customComponents.myOrgChart.TestIR" />
<s:GridColumn dataField="col9" itemRenderer="customComponents.myOrgChart.TestIR" />
<s:GridColumn dataField="col10" itemRenderer="customComponents.myOrgChart.TestIR" />
</s:ArrayList>
</s:columns>
</s:DataGrid>
这个DataGrid 的DataProvider 是一个ArrayCollection,它包含10 个Objects 属性col1 - col10,其中每个属性的类型都是CellRendererVO。
这是这个实现的输出:
现在麻烦来了
我有按钮Hide Images,如上图所示。需要做的是,当单击此按钮时,必须隐藏 Org.Chart 中显示的所有图像。但是等等,我只是坚持其他事情,现在忘记这个实现。
此按钮的点击处理程序如下:
private function hideImagesBtn_clickHandler(event:Event):void
{
orgChartDP.refresh();
}
但是,当单击此按钮时,我看到了一个奇怪的行为。单击 Hide Images 时查看 Org.Chart 的输出:
我无法弄清楚它为什么会如此变化。如您所见,只有refresh 的ArrayCollection 正在完成。为什么Org.Chart 的整体结构发生了变化?
我对此进行了一些研究,我能想到的一个原因是ItemRenderers 的 reusable 功能。但是,这个原因仍然不适用于Org.Chart的变更。
感谢您来到这里为解决此问题提供任何帮助。
谢谢, 安吉
【问题讨论】:
-
我必须承认我还没有完全阅读你冗长的问题,但是为什么为了 [insert divinity of choice] 的缘故你试图将流程图塞进数据网格?
-
或许更有帮助:看看Kalileo。有一个免费的社区版;不过,商业许可证相当昂贵。
-
@RIAstar 我已经更新了我的问题。感谢您让我知道
Kalileo。我想了解为什么要这样绘制(就我而言)。我希望这次学习可以帮助我详细了解 flexItemRenderers。 -
你为什么要使用 Datagrid 呢?你应该有一个完全不同类型的 Object 。 DG 中的渲染器。构建这样一个组织结构图可能不是世界上最好的主意。我知道我可能听起来很奇怪,但组织结构图不是数据网格。您应该从 canvas/uiComponent 开始从头开始创建组件,以避免刷新问题和性能问题。
-
@Anji google 上有一些不错的组织结构图示例。您所要做的就是稍微研究一下它们,如果您了解 core 或 flex,那么您就会知道 datagrid 不是最佳选择。这里有一些链接blog.frankula.com/?p=148和coolestflex.blogspot.com/2008/10/…
标签: actionscript-3 apache-flex datagrid flex4 itemrenderer