月度归档:2011年04月

Camix – 在线摄像头拍照

终于花了些时间,把Camix搞出来了一个预览版,其实更像是原型,这个项目我计划了约有两年多吧,一直因为各种事情搁置下来。

虽然这版界面很丑,操作不人性化,没有接入Server端,等等的各种问题,至少对我个人来讲是个一大步。尽管我对这个项目有个Big Picture,只是我这个人往往对自己的事情最不负责,而对给别人做事特负责,所以下一班不一定是什么时候了:)

 

发个截图先, (访问地址:http://www.nealmi.com/index.php/camix/ )

明天?何须担忧,太阳照常升起!

关于我的 Flex Gallery 博客

发布的时候内容丢失,很崩溃。不想重写了!

简要阐述下吧:

  • 2008年开始,在Blogger上,地址 http://coolestflex.blogspot.com
  • 2010年使用DiaHosting的备份开始测试迁移。
  • 2011年完全迁移到 ServerPronto 的独立Server, 目前地址:http://wp.nealmi.com, Blogger 上的关闭。
  • 接下来,持续地,缓慢的更新。

 

志存高远,厚积薄发,继续沉默地,前行。让我们面对现实,让我们忠于理想!

限制 Flex PopUp 的拖动区域

使用Flex的PopUpManager, 也许很多人都遇到过,弹出一个可以拖动的TitleWindow,结果不小心给拖动到了Flex应用的外部,结果TitleWindow的标题栏被浏览器的工具栏给挡住了,无法拖动回来。这个是让人很崩溃的问题。

我一直认为这是Flex的一个bug。可惜官方没有重视这个问题。其实解决办法也有不少,其他的我在这里就不说了,我还是喜欢最简单最有效的办法来解决问题。

思路:通过阅读 Panel 里面Drag相关的代码你会发现,最后StopDrag会调用 move 方法。所以就可以监听move事件,限制拖动区域。

1.在弹出的时候加入move的监听

2.在move的监听里判断组件的 y 值。如果超出有效值(保证在组件在Flex应用内),设置成临界值。

代码:

var pop:SomeComp = new SomeComp();
pop.addEventListener(MoveEvent.MOVE, moveMe);
PopUpManager.addPopUp(pop, FlexGlobals.topLevelApplication as DisplayObject, true);
PopUpManager.centerPopUp(pop);
private function moveMe(e:Event):void {
	var target:UIComponent=e.target as UIComponent;
	var targetX:Number=target.x;
	var targetY:Number=target.y;
	var appWidth:Number=FlexGlobals.topLevelApplication.width;
	var appHeight:Number=FlexGlobals.topLevelApplication.height;
	
	if (targetY < 10) {
		target.y=10;
	}
	if (targetY > appHeight - 30) {
		target.y=appHeight - 30;
	}
}
	

实现Flex DataGrid 可以复制整行值的 itemRenderer

几个关键点:

  • 实现IListItemRenderer 和 IDropInListItemRenderer接口,Label默认已经实现
  • 覆盖 data 属性 setter(这个是一行的数据,不是一个单元格的数据)
  • (如果需要,本例不需要)通过 listData 属性获得单元格的元数据(dateField,columnIndex 等等)信息
  • 通过 owner 属性获得 DataGrid,从而获得所有列的信息
  • 根据列信息拼接 data 到字符串
  • 通过 Clipboard 把字符串放到操作系统的 Clipboard 里面
  • 添加右键上下文菜单
package com.nealmi.ui.lib.itemrenders {
	import flash.desktop.Clipboard;
	import flash.desktop.ClipboardFormats;
	import flash.events.ContextMenuEvent;
	import flash.ui.ContextMenu;
	import flash.ui.ContextMenuItem;

	import mx.controls.Label;
	import mx.controls.dataGridClasses.DataGridListData;
	import mx.controls.listClasses.BaseListData;


	public class CopyableDataGridItemRenderer extends Label {
	
		private var cellValue:String="";

		public function CopyableDataGridItemRenderer() {
			super();
		}

		override public function set data(value:Object):void {
			if (!value) {
				return;
			}
			super.data=value;
			cellValue = "";
			//cellValue=data[(this.listData as DataGridListData).dataField];
			var pt:mx.controls.DataGrid=listData.owner as mx.controls.DataGrid;
			if (!pt)
				return;
			//拼接该行所有数据为字符串,并且去除无dataField的列(比如趋势按钮列)
			for each (var c:mx.controls.dataGridClasses.DataGridColumn in pt.columns) {
				if (c.dataField == null || c.dataField == "" || c.dataField == "undefined")
					continue;
				cellValue+=data[c.dataField] + ",";
			}
			if (cellValue && cellValue.length > 1) {
				//去掉最后一个逗号
				cellValue=cellValue.substr(0, cellValue.length - 1);
				//设置toolTip
				this.toolTip=cellValue;
				//添加上下文菜单(右键菜单)
				var myMenuItem:ContextMenuItem=new ContextMenuItem("复制该行值");
				myMenuItem.addEventListener(ContextMenuEvent.MENU_ITEM_SELECT, copyValueToClipBoard);
				var myMenu:ContextMenu=new ContextMenu();
				myMenu.hideBuiltInItems();
				myMenu.customItems.push(myMenuItem);
				this.contextMenu=myMenu;
			}
		}

		override protected function updateDisplayList(w:Number, h:Number):void {
			super.updateDisplayList(w, h);
			if (textField) {
				//文字居中
				textField.y=(h - textField.textHeight) * 0.5;
			}
		}


		private function copyValueToClipBoard(e:ContextMenuEvent):void {
			if (cellValue) {
				Clipboard.generalClipboard.setData(ClipboardFormats.TEXT_FORMAT, cellValue);
			}
		}
	}
}