Java开发网 |
注册 |
登录 |
帮助 |
搜索 |
排行榜 |
发帖统计
|
您没有登录 |
» Java开发网 » Java GUI 设计
打印话题 寄给朋友 订阅主题 |
作者 | 震动的窗口 |
polygoncell
发贴: 14 积分: 2 |
于 2005-11-30 23:27
今天在网上看到了一个很有趣的关于Swing扩展的小例子,觉得很有意思,我把他的代码稍微作了些改进,需要的朋友可以立刻在项目中使用。 这个例子主要是为了实现一个“震动”的对话框,原文对源代码进行了很详细的解释,希望英文好的朋友直接去看原文,然后再回来继续看我的文章,原文的连接附在文章的最后。 下面的代码已经被我做了适当的修改,在代码中, 我也添加了适当的注释, public class DialogEarthquakeCenter extends Object { // 窗口距离中心左右晃动的最大距离 public static final int SHAKE_DISTANCE = 10; // 窗口晃动一个循环(中间,右,中间,左, 中间)所需要的时间(ms), // 这个值越小, 晃动的就越快。 public static final double SHAKE_CYCLE = 80; // 整个晃动所需要的时间。 public static final int SHAKE_DURATION = 300; // 这个是设定Swing多长时间(ms)更新窗口的位置。 public static final int SHAKE_UPDATE = 5; private JDialog dialog; private Point naturalLocation; private long startTime; private Timer shakeTimer; private final double HALF_PI = Math.PI / 2.0; private final double TWO_PI = Math.PI * 2.0; public DialogEarthquakeCenter (JDialog d) { dialog = d; } public void startShake() { // 保存窗口的原始位置 naturalLocation = dialog.getLocation(); // 保存开始的时间 startTime = System.currentTimeMillis(); shakeTimer = new Timer(SHAKE_UPDATE, new ActionListener() { public void actionPerformed (ActionEvent e) { // 计算倒目前为止花费的时间 long elapsed = System.currentTimeMillis() - startTime; // 下了三角公式是为了利用时间计算出某一时刻晃动的幅度,举例见A. double waveOffset = (elapsed % SHAKE_CYCLE) / SHAKE_CYCLE; double angle = waveOffset * TWO_PI; double angley = waveOffset * TWO_PI; int shakenX = (int) ((Math.sin(angle) * SHAKE_DISTANCE) + naturalLocation.x); int shakenY = (int) ((Math.sin(angley) * SHAKE_DISTANCE) + naturalLocation.y); dialog.setLocation (shakenX, shakenY); dialog.repaint(); // should we stop timer? if (elapsed >= SHAKE_DURATION) stopShake(); } } ); shakeTimer.start(); } public void stopShake() { shakeTimer.stop(); dialog.setLocation (naturalLocation); dialog.repaint(); } // 去掉了原始代码中的main } A. 下面我来解释一下这里用到的三角函数,其实非常简单,其目的就是让窗口流畅的晃动。 double waveOffset = (elapsed % SHAKE_CYCLE) /SHAKE_CYCLE; 由于窗口是在相对于他的原始位置做周期震动,这个公式是为了将震动的时间换算成相对震动一周的相对比例,举例来说就是:(%是取余运算) 20ms时,震动了1/4周,waveOffset = (20%80)/80 = 0.25, 到右边最远处。 40ms时,震动了半周, waveOffset = (40%80)/80 = 0.5, 回到起点位置。 60ms时,震动了3/4周,waveOffset = (60%80)/80 = 0.25, 到左边最远处。 80ms时,整好震动一周, waveOffset = (80 %80)/80 = 0, 回到起点位置。 然后继续循环 double angle = waveOffset * TWO_PI 将上述介于0到1的比例换算成角度,也就是20ms-1/4周-PI/2。 int shakenX = (int) ((Math.sin(angle) * SHAKE_DISTANCE) + naturalLocation.x); 然后再将角度利用sin函数换算成相对应的震动幅度。到这里可能会有朋友要问,问什么不利用时间比例waveOffset直接换算成震动幅度, 就是好象这样: int shakenX = (int) ((waveOffset* SHAKE_DISTANCE) + naturalLocation.x); 这样也是可以的,利用三角函数可以使振动更加圆滑更加真实,因为y = sin(x)函数波浪形的曲线,结果是靠近中心的地方震动幅度变化的比较快,远离中心的地方震动幅度变化的比较慢。而使用waveOffset直接换算成震动幅度使用的是y=ax函数,他的函数图是直线,导致震动幅度变化比较生硬。 原始的代码里面只是设置了x方向的震动,我又加入了y方向的震动,并且调整了一些参数,使得震动比较柔和。 还有就是,原始代码是含有main方法的application。在实际开发中根本没用,我把她改写成了一个简单的类。在实际开发中只要在DialogFactory里面增加一个方法生成这种对话框就可以了,编码人员可以轻松使用,i.e. 。DialogFacotry.createShakeMessageDialog(……) Public final class DialogFactory { …… // 这里使用enum是为了实现I18N,如果不需要的话,可以直接使用String private void createShakeMessageDialog(Enum title, Enum message) { // 作为例子,这里只是生成一个简单的信息框,只带有一个ok按钮。 JOptionPane pane = new JOptionPane(message.localized(), JOptionPane.INFORMATION_MESSAGE, JOptionPane.DEFAULT_OPTION, null, null, null); JDialog dialog = pane.createDialog(DialogFactory.defaultFrame(), title.localized()); DialogShaker shaker = new DialogShaker(dialog); dialog.pack(); // 这个很关键,一定要设为false dialog.setModal(false); dialog.setVisible(true); shaker.startShake(); } ...... //其他方法。 } 原文:http://www.oreilly.com/catalog/swinghks/chapter/hack38.pdf 请关注我的blog http://spaces.msn.com/members/polygoncell/ http://blog.csdn.net/schnell/
polygoncell edited on 2005-12-02 17:32
从Coding Fan到真正的技术专家 |
话题树型展开 |
人气 | 标题 | 作者 | 字数 | 发贴时间 |
4626 | 震动的窗口 | polygoncell | 5128 | 2005-11-30 23:27 |
3817 | Re:震动的窗口 | polygoncell | 18 | 2005-12-01 17:39 |
已读帖子 新的帖子 被删除的帖子 |
Powered by Jute Powerful Forum® Version Jute 1.5.6 Ent Copyright © 2002-2021 Cjsdn Team. All Righits Reserved. 闽ICP备05005120号-1 客服电话 18559299278 客服信箱 714923@qq.com 客服QQ 714923 |