搭建Java桌面应用措施原型(三)
做技能抉择
在开拓进程中,我不得不去办理一些技能问题而且要做一些技能抉择。下面的代码片断仅仅简朴的举办了表明,可是他们将在我今后的文章中被具体描写。在这里重要的是去领略原型充当的脚色。用你的原型去寻找技能问题的办理方案,去测试不常用的APIs,而且担保你的应用措施的机能。
用多层Panels
构建一个譬喻windows中的画板的图形应用措施不长短常巨大的任务。你必需处理惩罚鼠标事件、画线、画矩形和画椭圆。还要处理惩罚变形成果,好比从一个基本应用措施到一个专业级的图形编辑器要具有对图片的移动,缩放,从头排序、删除、复制、剪切和粘贴等更多的事情。你也可以想要包括一个可以举办编辑、从头节制巨细和文字包装成果的文字框等等。构建本身的气势气魄文本编辑器是没有须要的,因为Swing已经提供了一些文本组件。
你怎么将Swing的文本编辑器和你本身的画图组件相集成?我思量了两个办理方案。一个是实现一个雷同于JTable所用的cell编辑器,可是假如你想改变文本框巨细可能移动它就需要一点能力了。另个一个办理方案是用JDesktopPane,把文本组件放在JInternalFrame之内。
用第二种办理方案的话,Swing已经提供了改变巨细和移动成果,可是下面的问题是你怎么在包括文本注释的内置frame下绘制图象?而且你怎么在JDesktopPane上绘制其他简朴图形,譬喻直线、矩形和椭圆?幸运的是,有一个简朴的办理方案,因为JDesktopPane是真正的多层Panel。原型的MainPane类扩展了JDesktopPane,有两层。它们中的一个包括PaintView自界说组件,答允你绘制简朴图形。另一层包括文本注释。虽然,假如一个注释图片不能被措施得到,那么这个办理步伐是没有意义的。MainPanel的getAnnotatedImage()要领操作下面的代码做这件事:
BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
Graphics2D g = image.createGraphics();
printAll(g);
g.dispose();
在paint()外部举办绘制
Swing组件的绘制凡是都是在paint()内部举办可能在paint()内部挪用绘制要领。当用鼠标在屏幕上绘制一个工具,但是,你不想重绘其他组件,因为这将引起应用措施运行效率低下。譬喻,用户用铅笔举办绘制,每个鼠标事件都让应用绘制一个小线段。在MOUSE_PRESSED和MOUSE_RELEASED之间有上百个MOUSE_DRAGGED事件。
当用户在屏幕仅仅绘制了一些图形时,重绘PaintView组件几百次这样的工作是不能被接管的。留意一下,PaintView处理惩罚大大都的绘制操纵而且一个repaint需要所有注释包罗文本注释举办重绘。正确的办理方案是当每个鼠标事件被处理惩罚时在paint()外部操作getGraphics()得到图形上下文。
protected void toolAction(MouseEvent e) {
e.consume();
Graphics2D g2 = (Graphics2D) getGraphics();
float zoomFactor = model.getZoomFactor();
g2.scale(zoomFactor, zoomFactor);
float x = e.getX() / zoomFactor;
float y = e.getY() / zoomFactor;
currentTool.action(e.getID(), x, y, g2);
g2.dispose();
}
PaintView组件操作鼠标监听去处理惩罚鼠标事件。上面的要领被每一个事件所挪用,委托绘制currentTool工具。当鼠标释放的时候,repaint()被挪用去请求整个组件的刷新。因此,用户完成图形工具绘制后paint()仅仅被挪用一次。这是注册鼠标监听的代码:
protected void registerListeners() {
addMouseListener(new MouseAdapter() {
public void mousePressed(MouseEvent e) {
if (SwingUtilities.isLeftMouseButton(e)) {
requestFocus();
currentTool = model.createTool(AbstractTool.DRAW_STYLE);
toolAction(e);
}
}
public void mouseReleased(MouseEvent e) {
if (SwingUtilities.isLeftMouseButton(e)) {
toolAction(e);
model.setLastTool(currentTool);
currentTool = null;
repaint();
}
}
});
addMouseMotionListener(new MouseMotionAdapter() {
public void mouseDragged(MouseEvent e) {
if (SwingUtilities.isLeftMouseButton(e))
toolAction(e);
}
});
...
}
PaintView类的完整代码将在今后的文章中报告。上面代码片断仅仅展示了怎么操作原型去做技能抉择。
总结
原型在应用措施开拓进程中有着重要的脚色,答允你测试你的想法而且尽早的得到用户反馈。我没有把原型当作是当“真正”开拓开始时可以被扬弃的代码片断。反而,原型应该是你产物可能着应用的基本。这意味着你应该小心的对它举办编码,尽量你的类或要领在今后要被重写。