正在阅读:轻松实现Java用户界面编程轻松实现Java用户界面编程

2005-07-11 10:02 出处: 作者:unknow 责任编辑:moningfeng

  发行包中包含示例程序的源代码,还有编译好的类文件和 Buoy 的 JAR 文件(单击本文顶部或底部的 Code 图标,下载 factal.tar)。包中还包含一个叫做 frac 的目录,里面包含一些示例分形。如果使用一台 UNIX 风格的机器,在路径中有 Java 编译器,那么只要运行 make 就能运行它。否则,需要设置 classpath 包含当前路径和 Buoy 的 JAR 文件所在的目录,然后运行 FractalViewer 类。在 Windows 系统上,正确的命令行应当是 java -classpath .;Buoy.jar FractalViewer。

  sed -e s/J/B/g

  在第一次深入研究代码时,也许会形成这样的印象:把 Swing 代码转换成 Buoy 代码简单得就像把 UI 元素名称中的字母 J 换成 B 一样简单。例如, FractalViewer 类不再扩展 JFrame;它现在扩展的是 BFrame。主要的小部件名称也可以照此推测得到。Spinner 和 slider 像以前一样有相同的名字,只是换了一个字母。 MenuBar(菜单条) 仍然由 Menus(菜单)构成,菜单则容纳 MenuItems。

  有些命名转换略有不同。在 Swing 引用 BorderLayout 的地方,Buoy 有 BorderContainer。一般来说,Buoy 的命名转换相当统一,虽然不总是与 Swing 的命名一样。一个明显的区别是 Buoy 几乎组合了容器和布局管理器的概念;每种容器类型都知道自己如何布局。这大大简化了设计。例如,在分形生成器中使用的 LabelWidget 类是一个 BorderContainer;在 Swing 中,这可能是一个带有 BorderLayout 布局管理器的 JPanel。

  但是,两者还是有许多相似之处。这对适应新东西有很大帮助。更重要的是,Buoy 构建在 Swing 之上。这意味着,一般来说,如果需要做的事不能轻松地用 Bouy 完成时,可以把 Buoy 对象传递给它包装的 Swing 对象。对于这种情况,如果想访问一些没有 Buoy 对应物的 Swing 对象,可以简单地把它包装在 AWTWidget 对象中,这个对象提供了非常薄的包装器,通过它,不仅 Buoy 自己的小部件,而且所有的小部件都能访问 Buoy 的小部件 API。例如,如果发现确实需要 GridBagLayout,可能就需要这样做。

  例如,FractalPanel 类是一个 AWTWidget。在早期设计中, 它是 JPanel 的子类, 但实际上我并不需要 JPanel 代码。相反,我构建了包装定制类的类 FractalCanvas, 它本身是普通的 Canvas 类的一个子类。把它变成一个 AWTWidget,就可以在它上面利用 Buoy 高效的事件处理机制。

  事件处理代码非常简单。在按下鼠标按钮时,通过 addEventLink() 的魔力,Buoy 发送一个新的 MousePressedEvent 事件到 mousePressed() 函数。我忽略了按下哪个按钮这个问题,只考虑按住 shift 单击或普通单击。普通单击选择最靠近的点,而按住 shift 单击则重新把显示居中。然后,如果鼠标移动,那么每次 Buoy 注意到移动时都会开始发送 MouseDraggedEvent 事件。在处理这些事件时,FractalPanel 会生成自己的事件。

  近观 PointChangedEvent

  为了让一些讨论更加具体,请来看 PointChangedEvent。这是一个试验性的类,如果不喜欢它,那也只能怪老天了。这个类的想法是:让一个类来表示状态点中的变化。编辑器跟踪“当前”点 —— 也就是编辑器小部件目前正在编辑的点。可以用这些小部件或在分形面板中单击选择新的点,选择的是最靠近的点。

  我得出这样一个结论:在代码中,大概有三类涉及到点的事件需要从一个类发送到另一个类。

  一个是改变某个点的特征: POINT 事件类型。如果由编辑器发送,就是告诉分形改变原型线条上的点,并要求重画线条。如果由分形发送,则是告诉编辑器刚刚选中的点的特性。

  下一个是选择某个点。可以按索引或位置进行选择。所以,如果只提供了索引或位置,那么构造函数会认为意图是填充其他值。有一点特殊的地方,点索引 -1 用来表示没有选中的点,所以必须用 -2表示编辑器正在寻找指定位置的点。这可能不漂亮,但是有效。

  有点意思的是 Fractal 类响应 SELECT 事件的方式。如果成功地选择了一个点,就会发回一个新的 POINT 类型的 PointChangedEvent 事件,如清单 1 所示。

  清单 1. 用事件回答事件

case PointChangedEvent.SELECT:
if (e.getIndex() >= -1)
selectPoint(e.getIndex());
else
selectPoint(e.getPoint());
// just in case they don't know
event(new FractalChangedEvent(FractalChangedEvent.SIZE, size));
if (selectedPoint >= 0 && selectedPoint < size)
event(new PointChangedEvent(selectedPoint, points[selectedPoint]));
else
event(new PointChangedEvent(selectedPoint, null));
event(new FractalChangedEvent(FractalChangedEvent.REDRAW));
break;



  最后,移动点是一个特殊情况,如果不需要改变点的其他属性(例如颜色),那么所要处理的就是位置。这就是 MOVE 事件类型。在效果上,它与 POINT 事件类型效果很像,但它不需要事件生成器(通常是 FractalPanel 类)去关心那些它根本不知道的属性。
键盘也能翻页,试试“← →”键

关注我们

最新资讯离线随时看 聊天吐槽赢奖品