Flex框架-甘特图开发

2012年,刚刚毕业参加的工作的时候,在公司里面学习了Flex技术。由于本人是做Java的,Flex中的ActionScript语法和Java挺类似,所以学起来还比较顺手的。大概做了一年多和Flex相关的软件开发,然后就跳槽专攻Java了。现在Flex貌似已经不算使用非常广泛的框架了,但是存在即合理,我相信使用Flex技术的公司或者兴趣爱好者还是不少的。由于本人对Flex研究也是皮毛,利用Flex做出特别NB的软件也没有。现在这里分享一下自己独立做的一个Flex项目--甘特图。
甘特图就是一个缩小版的Project,里面的功能也不是很复杂。但是当初以我的水平,开发起来还是步步都是坑。当你以一个新手入场的时候,你才会知道挨的每一拳到底有多痛。当初开发甘特图的时候,基本上就我一个,网上找相关的资料,特别是和Flex有关的资料,那是相当的少。基本上没有看到我想要的。所以在利用Flex开发甘特图这方面的问题也全靠自己去琢磨,去解决。
现在回头看看甘特图的功能,整体而言并没有特别突出的亮点,但是开发的这段经历却一直让我记忆犹新。一个人奋斗了大半年,基本上每天加班。也享受问题得到解决后的喜悦,也是这段经历让我对以后的码农之路坚定了信心。
当初甘特图是作为一个插件为另一个项目服务的,但是另一个项目开发失败,导致甘特图也白开发了,当时是无比的心塞!!!!呕心沥血大半年,一下回到解放前!!!
将3年前的东西分享出来,的确有些扯淡了,算是一个小小的总结吧。
重点开始!
甘特图和服务交互采用WebService,我相信做开发的人对WebService都很熟悉,不用赘述。
甘特图中最困难的当属任务条的绘制和渲染,还有就是连接任务关系等相关的线条绘制。同时还有网络图的绘制也比较麻烦。
甘特图任务渲染使用高级表格AdvancedDataGrid,并重写了里面的一些方法。

<span style="white-space:pre">		</span>override protected function mouseDoubleClickHandler(event:MouseEvent):void
		{
			var dataGridEvent:AdvancedDataGridEvent;
			var r:IListItemRenderer;
			var dgColumn:AdvancedDataGridColumn;
			r=mouseEventToItemRenderer(event);
			if (r && r != itemEditorInstance)
			{
				try
				{
					var dilr:IDropInListItemRenderer=IDropInListItemRenderer(r);
					if (columns[dilr.listData.columnIndex].editable)
					{
						dgColumn=columns[dilr.listData.columnIndex];
						dataGridEvent=new AdvancedDataGridEvent(AdvancedDataGridEvent.ITEM_EDIT_BEGINNING, false, true);
						// ITEM_EDIT events are cancelable
						dataGridEvent.columnIndex=dilr.listData.columnIndex;
						dataGridEvent.dataField=dgColumn.dataField;
						dataGridEvent.rowIndex=dilr.listData.rowIndex + verticalScrollPosition;
						dataGridEvent.itemRenderer=r;
						dispatchEvent(dataGridEvent);
					}
				} 
				catch(error:Error) 
				{
					
				}
				
			}
			super.mouseDoubleClickHandler(event);
		}
		/**
		*鼠标释放事件
		*/
		override protected function mouseUpHandler(event:MouseEvent):void
		{
			var r:IListItemRenderer;
			var dgColumn:AdvancedDataGridColumn;
			r=mouseEventToItemRenderer(event);
			if (r)
			{
				if (r is AdvancedHeaderRenderColumnMc || r is AdvancedHeaderRenderColumn)
				{
					return;
				}
				try
				{
					var dilr:IDropInListItemRenderer=IDropInListItemRenderer(r);
					if (columns[dilr.listData.columnIndex].editable)
					{
						dgColumn=columns[dilr.listData.columnIndex];
						dgColumn.editable=false;
					}
				} 
				catch(error:Error) 
				{
					
				}
				
			}
			super.mouseUpHandler(event);
			if (dgColumn)
				dgColumn.editable=true;
		}
		


对于表格中可移动的组件需要使用自定义组件,大部分时间都花在了调试自定义组件上面。
<mx:LinkButton width="16"
				   height="16"
				   enabled="true"
				   click="doClick()"
				   y="{(GanttProperties.RowHeight - 16)/4 - 3}"
				   id="openbutton"
				   x="{offSize-20}"
				   icon="@Embed('icon/gantt_open.png')">
	</mx:LinkButton>
	<!--
	{GanttProperties.GanttEditor}
	-->
	<s:HSlider id="ganttitem"
			   enabled="{GanttProperties.GanttEditor}"
			   skinClass="com.gantt.diycolumn.MyHSlider"
			   minWidth="1"
			   width="{ganttWidth}"
			   height="{GanttProperties.GanttItemHeight}"
			   y="{(GanttProperties.RowHeight - GanttProperties.GanttItemHeight)/4 -4}"
			   x="{offSize}"
			   minimum="0"
			   value="{data.percent}"
			   thumbRelease="release()"
			   thumbDrag="releaseing()"
			   thumbPress="releasePress()"
			   maximum="100"
			   dragEnter="doDragEnter(event)"
			   dragDrop="doDragDrop(event)"/>
	<mx:LinkButton x="{offSize+ganttWidth-14}"
				   enabled="false"
				   y="-2"
				   id="lingxing"
				   icon="{GanttProperties.stoneIcon}">
	</mx:LinkButton>

	<diycolumn:GanttItem id="actualGanttItem"
						 width="{actualDateWidth}"
						 visible="{GanttProperties.ActualDate}"
						 includeInLayout="{GanttProperties.ActualDate}"
						 height="7"
						 y="{(GanttProperties.RowHeight - 13)}"
						 x="{actualDateOffSize}">
	</diycolumn:GanttItem>

	<diycolumn:GanttItem id="estimatedGanttItem"
						 width="{estimatedTimeLineWidth}"
						 visible="{GanttProperties.EstimatedDate}"
						 includeInLayout="{GanttProperties.EstimatedDate}"
						 height="2"
						 bdcolor="0x12345ab"
						 y="{(GanttProperties.RowHeight - 8)}"
						 x="{actualDateOffSize}">
	</diycolumn:GanttItem>

	<mx:HBox id="assignment"
			 width="{assignmentWidth}"
			 height="{GanttProperties.RowHeight}"
			 visible="{GanttProperties.TaskAssignment}"
			 includeInLayout="{GanttProperties.TaskAssignment}"
			 horizontalGap="20"
			 y="0"
			 x="{offSize+ganttWidth+14}">

	</mx:HBox>

网络图中,需要用各种形状来表示不同类型的任务。每种形状也全是用UIComponent画出来的。
/**画出一个矩形*/
		public function drawRectangle():void
		{
			
			sprite.graphics.beginFill(color);
			sprite.graphics.lineStyle(2, bdcolor, 1, true);
			sprite.graphics.drawRoundRect(0, 0, width, height, 10, 10);
			//sprite.graphics.drawCircle(width,height/2,radio);
			sprite.graphics.endFill();
			
			leftPoint.x=0;
			leftPoint.y=height/2;
			rightPoint.x = width;
			rightPoint.y = height/2;
		
		}
		
		
		
		
		/**画出一个菱形*/
		public function drawRhombus():void
		{
			
			sprite.graphics.beginFill(color);
			var vec:Vector.<Number>=new Vector.<Number>();
			vec.push(0, height / 2);
			vec.push(width / 6, 0);
			vec.push(width * 5 / 6, 0);
			vec.push(width, height / 2);
			vec.push(width * 5 / 6, height);
			vec.push(width / 6, height);
			
			var vec2:Vector.<int>=new Vector.<int>();
			vec2.push(0, 1, 5);
			vec2.push(2, 3, 4);
			sprite.graphics.drawTriangles(vec, vec2);
			sprite.graphics.drawRect(width / 6, 0, width * 2 / 3, height);
			//sprite.graphics.drawCircle(width,height/2,radio);
			sprite.graphics.endFill();
			
			drawLine(vec);
			
			leftPoint.x=0;
			leftPoint.y=height/2;
			rightPoint.x = width;
			rightPoint.y = height/2;
		
		
		}
		
		/**画三角形*/
		public function drawTrangle():void
		{
			sprite.graphics.beginFill(color);
			var vec:Vector.<Number>=new Vector.<Number>();
			vec.push(0, height / 2);
			vec.push(width / 2, 0);
			vec.push(width, height / 2);
			
			sprite.graphics.drawTriangles(vec);
			sprite.graphics.endFill();
			drawLine(vec);
		}


甘特图里面,本人最不满意的就是表格中的线条绘制。因为在用线连接跨表格的任务时,没有找到很好的方法让绘制出来的线条和表格合二为一。我使用的绘制方法是将线条用Shape画在表格之上。从而导致线条都是悬浮在表格之上,看着怪怪的。我也没有找到什么解决办法,希望大牛能够多出对策。
public function draw():void
		{
			graphics.clear();
			with (graphics)
			{
				lineStyle(_thinkness, _color, _alpha, _pixelHinting, _scaleMode);
				moveTo(start.x, start.y);
				lineTo(end.x, end.y);
			}

			if (hasArrowHead)
			{
				drawArrowHead();
			}
		}

甘特图里面还有一个最短路径算法,这个算法网上也很多,只是改成了ActionScript实现而已。
/**
		 *
		 * 遍历从开始活动到结束活动的所有可能的路径:采用递归方式(如果后继任务集合为空,则表明到达结束,是一条成功路径,否则就继续遍历直到某个任务没有后继节点)
		 * <功能详细描述>
		 * @param allActivity
		 * @param pos
		 * @param arrOnePath
		 * @param arrAllPath
		 * @see [类、类#方法、类#成员]
		 */
		public  static function goAllPath(allActivity:Array,pos:int,arrOnePath:Array):void{
			arrOnePath.push(allActivity[pos]);
			var t:Object=allActivity[pos];
			var arrSucc:Array=t.successor;
			if(arrSucc.length==0){
				    //成功到达终点,是一条路径
					var completePath:Array=new Array();
					for each(var tt:Object in arrOnePath){
						completePath.push(tt);
					}
					CommonUtil.arrAllPath.push(completePath)
					return;
				
			}else{//对后继的每个活动进行检查
				for(var  i:int=0;i<arrSucc.length;i++){
					var activity:Object=arrSucc[i];
					var  k:int=lookInActivityDatasForPos(allActivity,activity);
					goAllPath(allActivity,k,arrOnePath);
					var nowNumber:int=arrOnePath.length;
					//将最新加入到arrOnePath的活动弹出,选择其他活动重新开始搜索
					if(nowNumber>=1)
						arrOnePath.pop();
				}	
			}

		}
		/**
		 *
		 * 对所有查找到的路径进行选择找出最关键路径(即耗时间最长的路径,可能有多条)
		 * <功能详细描述>
		 * @param allActivity
		 * @param allPath
		 * @see [类、类#方法、类#成员]
		 */
		public static function markCriticalPath(allActivity:Array):void{
            var  pathSum:Number=0;
			var  maxpathSum:Number=0;
			var  k:int=0;
			for(var i:int=0;i<CommonUtil.arrAllPath.length;i++){
				var criticalPath:Array=CommonUtil.arrAllPath[i];
                for(var j:int=0;j<criticalPath.length;j++){
					var activity:Object=criticalPath[j];
					pathSum+=parseFloat(activity.cxsj);
				}

				if(maxpathSum<pathSum){
					k=i;
					maxpathSum=pathSum;
					CommonUtil.pathnum.splice(0,CommonUtil.pathnum.length);
					CommonUtil.pathnum.push(k);
				}else if(maxpathSum==pathSum){
					k=i;
					CommonUtil.pathnum.push(k);
				}
				pathSum=0;
			}



		}	

以上只是挑了一些重点说了一下,现在就是上图了,没有最终效果的展示,说得再多也是耍流氓。






最终效果就是这样,现在看看,还是比较丑的。
  本人扣扣:826179140,有任何意见和想法的或者有需要源码的,可以联系本人。



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值