看大家都我当前进行的flex仿QQ这个项目还是有兴趣,在此就当前进度谈谈我的做法吧,欢迎拍砖。
目前已经完成:系统托盘,登陆(经典及2011选择登陆), 基本聊天,同时登陆几个账号,联系人列表
看下图吧:
基本构架是 : flex(air) + red5 + mysql,如图
聊天等同步信息访问red5,其它信息访问webserver, 所有数据库操作通过webserver来与数据交互。
flex端源码组成:
org.freeim.core: 基本核心框架,如基础组件、工具类、资源访问等
org.freeim.commons: 通用组件等
FreeIM: 项目主体入口
在FreeIM主要有两大模块:
1. 主产品(mainProduct),聊天
2. 插件, 音乐或游戏什么的
主产品是在安装文件中有的, 插件用户可选择性安装
首先讲下org.freeim.core中定义最基本的窗口定义:
package org.freeim.core.componentClasses
{
import flash.display.NativeWindowDisplayState;
import flash.events.MouseEvent;
import mx.core.UIComponent;
import mx.events.FlexEvent;
import org.freeim.core.componentClasses.events.FimWindowEvent;
import spark.components.Button;
import spark.components.Group;
import spark.components.Window;
[Event(name="closeWindow", type="org.freeim.core.componentClasses.events.FimWindowEvent")]
public class FimWindow extends Window
{
//-------------------------------------------------------------------
// Properties
private var _closeable :Boolean;
public function get closeable():Boolean
{
return _closeable;
}
public function set closeable(value:Boolean):void
{
_closeable = value;
}
private var _parentWindow :Window;
public function get parentWindow():Window
{
return _parentWindow;
}
public function set parentWindow(value:Window):void
{
_parentWindow = value;
}
// Properties
//-------------------------------------------------------------------
//-------------------------------------------------------------------
// Behavors
override public function minimize():void{
super.minimize();
dispatchEvent(new FimWindowEvent(FimWindowEvent.Min));
}
override public function maximize():void{
super.maximize();
if(maximizeButtonRef){
maximizeButtonRef.toolTip = "向下还原";
}
dispatchEvent(new FimWindowEvent(FimWindowEvent.Max));
}
override public function restore():void{
super.restore();
if(maximizeButtonRef){
maximizeButtonRef.toolTip = "最大化";
}
}
public function closeThis():void{
dispatchEvent(new FimWindowEvent(FimWindowEvent.Close));
}
public function startMove():void
{
this.nativeWindow.startMove();
}
public function notifyUser(type :String) :void{
this.nativeWindow.notifyUser(type);
}
// Behavors
//-------------------------------------------------------------------
public function FimWindow(parentWindow :Window = null)
{
super();
this.parentWindow = parentWindow;
this.showStatusBar = false;
this.systemChrome = "none";
this.transparent = true;
addEventListener(FlexEvent.CREATION_COMPLETE,function(e:FlexEvent) :void{
setButtons();
setControl();
setProperties();
});
}
//--------------------------------------------------------------------
// Buttons
private var controlBarRef :UIComponent;
private var maximizeButtonRef :Button;
private var minilizeButtonRef : Button;
private var closeButtonRef :Button;
protected function setMinilizeButton(minilizeButton :Button):void{
if(minilizeButton){
minilizeButtonRef = minilizeButton;
minilizeButtonRef.toolTip = "最小化";
minilizeButtonRef.addEventListener(MouseEvent.CLICK, function(e:MouseEvent):void{
minimize();
});
}
}
protected function setMaxminzeButton(maximizeButton :Button) :void{
if(maximizeButton){
maximizeButtonRef = maximizeButton;
maximizeButtonRef.toolTip = "最大化";
maximizeButtonRef.addEventListener(MouseEvent.CLICK, function(e:MouseEvent):void{
if(nativeWindow.displayState == NativeWindowDisplayState.MAXIMIZED){
restore();
}else{
maximize();
}
});
}
}
protected function setCloseButton(closeButton :Button):void{
if(closeButton){
this.closeButtonRef = closeButton;
closeButtonRef.toolTip = "关闭窗口";
closeButtonRef.addEventListener(MouseEvent.CLICK, function(e:MouseEvent):void{
closeThis();
});
}
}
protected function setButtons() :void{
}
protected function setContrlBar(controlBar :UIComponent) :void{
if(controlBar){
controlBarRef = controlBar;
controlBarRef.doubleClickEnabled = true;
if(maximizable){
controlBarRef.addEventListener(MouseEvent.DOUBLE_CLICK, function(e:MouseEvent):void
{
if(nativeWindow.displayState == NativeWindowDisplayState.MAXIMIZED){
restore();
}else{
maximize();
}
});
}
controlBarRef.addEventListener(MouseEvent.MOUSE_DOWN, function(e:MouseEvent):void
{
startMove();
});
}
}
protected function setControl() :void{
}
// Buttons
//--------------------------------------------------------------------
protected function setProperties() :void{
}
override protected function createChildren():void{
super.createChildren();
}
}
}
此类只定义窗体的基本行为,具体呈现方式不进行定义,以便子类扩展不同风格或布局的窗体,在子类中要做的几件事就是,设置控制bar及按钮,如经典登陆窗口如下:
<?xml version="1.0" encoding="utf-8"?>
<componentClasses:FimWindow xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx"
xmlns:componentClasses="org.freeim.core.componentClasses.*"
width="389" height="288" closeable="true"
closeWindow="fimwindow1_closeWindowHandler(event)" maximizable="false"
resizable="false"
skinClass="org.freeim.commons.components.skins.window.WindowCommonSkin"
title="QQ2011">
<componentClasses:layout>
<s:VerticalLayout gap="0" horizontalAlign="center">
</s:VerticalLayout>
</componentClasses:layout>
<fx:Declarations>
<!-- Place non-visual elements (e.g., services, value objects) here -->
</fx:Declarations>
<fx:Script>
<![CDATA[
import mx.core.FlexGlobals;
import org.freeim.core.componentClasses.events.FimWindowEvent;
import org.freeim.core.utils.ScreenUtils;
import org.freeim.version.Version;
import spark.components.Window;
public static const WINDOW_ID :String = "loginWindow";
override protected function setControl():void{
setContrlBar(contolBar);
}
override protected function setButtons():void{
setMinilizeButton(minBnt);
setCloseButton(closeBnt);
}
protected function fimwindow1_closeWindowHandler(event:FimWindowEvent):void
{
close();
FlexGlobals.topLevelApplication.exit();
}
override protected function setProperties():void{
titleDisplay.text = title;
}
public static function open(parentWindow :Window = null) :LoginWindow{
var loginWindow :LoginWindow = new LoginWindow();
loginWindow.parentWindow = parentWindow;
loginWindow.id = LoginWindow.WINDOW_ID;
loginWindow.title = Version.VERSION;
loginWindow.open(true);
ScreenUtils.centerScreen(loginWindow);
loginWindow.notifyUser(NotificationType.CRITICAL);
return loginWindow;
}
protected function button1_clickHandler(event:MouseEvent):void
{
SettingWindow.open(this);
}
]]>
</fx:Script>
<s:HGroup id="contolBar" width="100%" height="25" gap="0" verticalAlign="middle">
<s:Label id="titleDisplay" width="70%" fontWeight="bold" paddingLeft="5">
</s:Label>
<s:HGroup width="30%" height="100%" gap="0" horizontalAlign="right">
<s:Button id="minBnt"
skinClass="org.freeim.commons.components.skins.button.MinimizeButtonSkin"/>
<s:Button id="closeBnt"
skinClass="org.freeim.commons.components.skins.button.CloseButtonSkin">
</s:Button>
</s:HGroup>
</s:HGroup>
<s:BitmapImage width="99.5%" height="101" fillMode="scale" horizontalCenter="0"
source="@Embed('./assets/image/login_logo.jpg')"/>
<s:SkinnableContainer width="99.5%" backgroundAlpha="0.92" backgroundColor="#F3F7FA"
horizontalCenter="0">
<s:layout>
<s:VerticalLayout gap="10" horizontalAlign="center">
</s:VerticalLayout>
</s:layout>
<s:HGroup width="100%" gap="10" horizontalAlign="center" verticalAlign="middle">
<s:BitmapImage fillMode="clip" source="@Embed('./assets/image/user_head.jpg')"/>
<s:Form defaultButton="{loginBt}">
<s:layout>
<s:FormLayout gap="0"/>
</s:layout>
<s:FormItem height="30">
<s:layout>
<s:HorizontalLayout verticalAlign="middle">
</s:HorizontalLayout>
</s:layout>
<s:ComboBox id="username" width="150">
</s:ComboBox>
<s:Label color="#4793c8" text="注册账号"/>
</s:FormItem>
<s:FormItem height="30">
<s:layout>
<s:HorizontalLayout verticalAlign="middle">
</s:HorizontalLayout>
</s:layout>
<s:TextInput id="password" width="150" displayAsPassword="true">
</s:TextInput>
<s:Label color="#4793c8" text="忘记密码"/>
</s:FormItem>
<s:FormItem>
<s:layout>
<s:HorizontalLayout verticalAlign="middle">
</s:HorizontalLayout>
</s:layout>
<s:CheckBox label="记住密码"/>
<s:CheckBox label="自动登陆"/>
</s:FormItem>
</s:Form>
</s:HGroup>
<s:SkinnableContainer width="100%" height="30" backgroundAlpha="0.9"
backgroundColor="#C0E5F3">
<s:Button left="10" width="70" height="22" label="多账号"
skinClass="org.freeim.commons.components.skins.button.ButtonSkin"
verticalCenter="0"/>
<s:Button left="90" width="70" height="22" label="设置" click="button1_clickHandler(event)"
skinClass="org.freeim.commons.components.skins.button.ButtonSkin"
verticalCenter="0"/>
<s:Button id="loginBt" right="10" width="70" height="22" label="登陆"
skinClass="org.freeim.commons.components.skins.button.ButtonSkin"
verticalCenter="0"/>
</s:SkinnableContainer>
</s:SkinnableContainer>
</componentClasses:FimWindow>