最近一段时间在公司闲着没事做,一向只倾心与java老大就启动了一个实验性项目,也就是用java做前端用户界面取代目前公司普遍用的C++开发的界面。之前用javaFX实验过一段时间,苦于没有好的设计器,完全违背了敏捷开发的初衷。鉴于netbeans目前的设计器还比较OK了,虽然生成的代码冗长拖沓。但是java的最大优势就是开源可以自行修改源码,自行设计组件,自行修改设计器....
说干就干,拿了我们公司业务最复杂的一个页面流程做实验。在设计上采用了界面和数据完全分离,借鉴于javaFx数据绑定概念。UI的操作更新绑定的数据模型内容,数据模型再发布事件通知UI刷新。基于这种思想,我们用设计器设计好界面,基本不要在里面写太多其他业务逻辑除了调用绑定数据模型的get/set方法和注册UI刷新事件外。
也许很多人认为Swing开发界面最大的瓶颈就是速度问题。这个也是我们优先考虑的,因为我们公司很多终端机都是128M内存,奔3时代老掉牙的机器。通过大量优化工作,老大为此鏖战几个通宵哦。目前在老机器下,与原来C++终端程序并行运行,在分配最大32M内存的情况,整个页面加载出来需要2秒,界面切换1秒~1.5秒之间,与原来C++同种程序大概差不多。整个项目图片比较多,就不发布出来了,先看看预览图片,如果有对此感兴趣同仁,我将把我们用到的优化方案分享出来,也大家一起研究学习。
UI部分代码片段:
数据模型代码片段:
[img]http://dl.iteye.com/upload/attachment/159660/6d91ed5b-a7fe-3133-8e88-858e26d48bfa.jpg[/img]
[img]http://dl.iteye.com/upload/attachment/159662/af4b7875-b2e6-3887-a4a5-189743416dc3.jpg[/img]
说干就干,拿了我们公司业务最复杂的一个页面流程做实验。在设计上采用了界面和数据完全分离,借鉴于javaFx数据绑定概念。UI的操作更新绑定的数据模型内容,数据模型再发布事件通知UI刷新。基于这种思想,我们用设计器设计好界面,基本不要在里面写太多其他业务逻辑除了调用绑定数据模型的get/set方法和注册UI刷新事件外。
也许很多人认为Swing开发界面最大的瓶颈就是速度问题。这个也是我们优先考虑的,因为我们公司很多终端机都是128M内存,奔3时代老掉牙的机器。通过大量优化工作,老大为此鏖战几个通宵哦。目前在老机器下,与原来C++终端程序并行运行,在分配最大32M内存的情况,整个页面加载出来需要2秒,界面切换1秒~1.5秒之间,与原来C++同种程序大概差不多。整个项目图片比较多,就不发布出来了,先看看预览图片,如果有对此感兴趣同仁,我将把我们用到的优化方案分享出来,也大家一起研究学习。
UI部分代码片段:
private void onBallClicked(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_onBallClicked
int index = Integer.parseInt(evt.getActionCommand());
dataModel.setSelectedCoordinate(new Integer[]{row, index});
}//GEN-LAST:event_onBallClicked
private void onBallChooseAction(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_onBallChooseAction
Ball ball = (Ball) evt.getSource();
ball.setImage(ball.getPressedImage());
String cmd = evt.getActionCommand();
dataModel.setChooseBall(Integer.parseInt(cmd),true);
}//GEN-LAST:event_onBallChooseAction
数据模型代码片段:
public void setChooseBall(Integer chooseBall) {
printLog("","当前输入球号码:"+chooseBall);
if(isDuplicate(chooseBall,chooseTotal))
return;
this.chooseBall = chooseBall;
updateSSQdataModel(true);
fireRefreshUIEvent(RefreshUIEvent.DOREFRESH);
}
private void updateSSQdataModel(boolean isAddBall) {
if (isAddBall) {
currentBallAmount++;
int x = (currentBallAmount -1)/ 7;
int y = currentBallAmount % 7 - 1;
if (y < 0) {//选择篮球结束
y = 6;
finishedOne = true;
chooseTotal++;
printLog("当前选择第"+chooseTotal+"注号码",data[x]);
}else{
finishedOne = false;
}
data[x][y] = chooseBall;
nextChooseIsBlue = (y == 5);
sort(x);
}
totalAmount = chooseTotal * multiples * 2;
printLog("","\n下一个球:"+(nextChooseIsBlue?"蓝球":"红球") +
"\n当前完成投注数:"+chooseTotal +"\n倍数:"+multiples + "\n总金额:"+totalAmount);
}
/**
* 自动选号
*/
public void autoChoose(){
//设置当前注生成为未完成状态
finishedOne = false;
if(chooseTotal>=5){
chooseTotal--;
}
currentBallAmount = chooseTotal * 7;
for (int i = 0; i < data[chooseTotal].length - 1; i++) {
currentBallAmount++;
chooseBall = generateRedNumber();
data[chooseTotal][i] = chooseBall;
}
generateBlueNumber();
// printLog("自动选号",data[chooseTotal]);
}
/**
* 生成红球
* @return
*/
private Integer generateRedNumber() {
for (;;) {
double random = Math.random();
int value = (int)(random*34);
if(value<=0 || value>33)
continue;
if(isDuplicate(value,chooseTotal))
continue;
return new Integer(value);
}
}
[img]http://dl.iteye.com/upload/attachment/159660/6d91ed5b-a7fe-3133-8e88-858e26d48bfa.jpg[/img]
[img]http://dl.iteye.com/upload/attachment/159662/af4b7875-b2e6-3887-a4a5-189743416dc3.jpg[/img]