`
bjxagu
  • 浏览: 165348 次
  • 性别: Icon_minigender_1
  • 来自: 长沙
社区版块
存档分类
最新评论

搭建Java桌面应用程序原型(一)

阅读更多

在这篇文章里,我将描述一个Java桌面应用的原型,我把它叫做JImageing。我打算把焦点集中在应用的框架上,解释我怎么做技术上的决定和我怎么解决在开发过程中出现的问题。

  为什么要建造一个原型?

  很多应用程序的开发都是由于几个原因从一个原型开始的。这些原因中的第一条就是,你必须确定用现有的技术能够满足用户的需求。例如,在不用本地代码的Swing应用程序中Windows集成不能够被实现,这就导致丧失了一些Java跨平台的优势。SWT提供了一个和操作系统有限制的集成,这就允许你在很多本地平台上运行同一应用程序。在很多场合,J2SE平台提供给你需要搭建复杂桌面应用程序的丰富性能。在搭建大型Java桌面工程之前,你总是应该搭建一个原型去看J2SE是否满足应用程序的需求。

  另一方面证明你的想法能够被实现并且你的技术决定是正确的,一个原型能够在开发过程中尽早的获得用户的反馈。原型也能帮助你估计完成你的工程所需要的时间和资源。花大量的工作去搭建一个有着菜单,对话框,拖拽特性、剪切版支持、恢复管理、打印等功能的用户接口。在开始这些工作之前,你应该知道搭建应用程序核心功能有多困难。如果你不得不用第三方自定义组件,你应该测试他们看看是否能和你的原型一起工作。如果你不得不解决扩展和性能问题,你应该通过原型状态找到解决方案。

  用户需求

  JImageing原型是一个桌面应用程序,这个应用程序允许你给图片注释。Email可能是最流行的“协作工具”,但是可以通过图片工具提高在截图上做注释的能力,这种图片工具可以让你画线,画矩形、椭圆并且可以写注释信息在图片上。

  如果JImageing的用户使用一个以上的操作系统,那么对于这样的一个应用程序Java是很自然的选择。当Windows支配桌面市场的时候,有一些用户选择Mac或者Linux。例如,当Java开发者通过互联网对一个项目进行合作的时候,有一可能性是他们可以不用同一种操作系统。

  这个用户接口非常简单,它包括一个工具栏和一个画图区。对于测试应用程序的主要功能来说足够用了。下图显示了这个接口的样子:

包和类

  下图显示了原型代码结构。应用程序的最顶层的包仅仅包含Main类,下段再详细介绍这个类。我将要描述在将来文章中可能用到的其他类。


  frames包囊括了描述应用程序主框架类,基于JDesktopPane的主要panel,和基于JInternalFrame文字注释类。这三个类被命名为MainFrame, MainPanel和NoteFrame。

  paint包组织了PaintView组件和它的数据模型(被命名为PaintModel),还有ToolBarBuilder类,这个类创建应用程序的工具栏。tools子包有绘制图象对象的工具类。

  resources包中的ResourcesSupport类是处理ToolBarResources.properties资源和来自images目录中的图标的工具类。

  The Main Class

  这个类实现了应用程序的main方法并且和所有的类、资源打包成一个JAR文件,这个JAR文件命名为JImageing.jar。用下面的命令进行打包:

  jar cfm JImaging.jar m.txt com

  com目录包含包里的类,.properties资源和.gif图标。

  m.txt文件用Main-Class: com.devsphere.articles.desktop.Main简要说明了应用程序的主要类。

  jar工具拷贝m.txt文件到在JImageing.jar中自动创建的META-INF/manifest.mf文件。

  下面是Main的主要声明描述:

package com.devsphere.articles.desktop;

import com.devsphere.articles.desktop.frames.MainFrame;
import com.devsphere.articles.desktop.frames.MainPanel;

import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

import javax.imageio.ImageIO;

import java.awt.image.BufferedImage;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;

import java.io.File;
import java.io.IOException;

import java.util.logging.Logger;

  main()方法调用Main()构造器,设置外观,创建主要窗口然后显示它:

public class Main {
 private String args[];
 private MainFrame mainFrame;
 private MainPanel mainPanel;

 private Main(String args[]) {
  this.args = args;
 }

 public static void main(String args[]) {
  Main main = new Main(args);
  main.setSystemLookAndFeel();
  main.createFrame();
  main.showFrame();
 }
 ...
}

  命令行可以包含一个或两个参数。用户能指定一个图片资源路径作为第一个参数。应用程序加载和显示图片,允许用户对它进行注释。如果第二个参数存在,那么应用程序保存注释过的图片到这个参数所给定的文件路径。运行应用程序,下面的命令行启动它:

java -jar JImaging.jar sourceImage annotatedImage

  J2SE能够加载GIF,JPEG和PNG文件,但是它仅仅能保存JPEG和PNG格式的图片。你可以不用GIF格式去保存注释过的图片。

 

 设置系统外观

  下面的setSystemLookAndFeel()方法调用了javax.swing.UIManager类的setLookAndFeel()方法:

  它要求Swing从默认的Metal外观转换为本地外观:

private void setSystemLookAndFeel() {
 try {
  UIManager.setLookAndFeel(
   UIManager.getSystemLookAndFeelClassName());
 } catch (UnsupportedLookAndFeelException x) {
  log(x);
 } catch (ClassNotFoundException x) {
  log(x);
 } catch (IllegalAccessException x) {
  log(x);
 } catch (InstantiationException x) {
  log(x);
 }
}

  通常,因为setLookAndFeel()参数都有一个可用值所以不会抛出异常。然而用标准日志API任何异常都可以作为严重错误信息被记录:

private static void log(Exception x) {
 Logger.global.severe(x.getMessage());
}


  原型安例中用全局日志是可以的,但是一个产品应该用它自己的日志,保存错误信息在文件中。

  创建并显示主要窗口

  createFrame()方法创建一个MainFrame实例,并且加载了图片:

private void createFrame() {
 mainFrame = new MainFrame();
 mainPanel = mainFrame.getMainPanel();
 mainPanel.updateSize();
 mainFrame.pack();
 loadImage();
}

  updateSize()设置了由getMainPanel()获得的主要面板的合理大小。pack()方法使得主框架调整大小从而让主面板和应用程序工具栏调整到合适的大小。注意到getMainPanel()和updateSize()方法是MainFrame和MainPanel类实现的应用方法。pack()方法是从java.awt.Window中继承下来的。

  showFrame()方法显示应用程序的主框架并且调用主panel的requestFocus()方法。没有调用requestFocus(),焦点将被工具栏中是缩放下拉框获得,这个组件不是框架的主要组件。当应用程序开始的时候,它的主要组件应该获得焦点,即使主要panel没有处理任何键盘事件。

  在窗口关闭的时候调用setDefaultCloseOperation(),禁用这个方法的默认动作而是传递DO_NOTHING_ON_CLOSE作为参数。showFrame()方法注册自己拥有的窗口监听器以便处理窗口关闭事件。当用户关闭主要框架,监听器保存一个做过注释的图片,释放框架所占用的资源并且用System.exit(0)结束应用程序的执行。

private void showFrame() {
 mainFrame.setDefaultCloseOperation(
  MainFrame.DO_NOTHING_ON_CLOSE);
 mainFrame.addWindowListener(new WindowAdapter() {
  public void windowClosing(WindowEvent e) {
   saveImage();
   mainFrame.dispose();
   System.exit(0);
  }
 });
 mainFrame.show();
 mainPanel.requestFocus();
}

  加载和保存图片

  一个完成的产品将用文件对话框去加载一个源图片并且保存一个注释过的图片。在观念上,“文件打开”对话框将让拥护预览图片,“文件保存”对话框将允许他们去提供不同的参数,例如保存图片的压缩质量。Swing的标准文件对话框是基于组件JFileChooser,这个组件能够通过setAccessory()方法进行自定义,让你在文件对话框上加载你的组件。

  在原型安例中,注意力应该在主要功能上。因此,原型通过从命令行获得加载和保存路径代替用自定义的文件对话框。javax.imageio.ImageIO类简单的read()和write()方法被用于加载和保存图片。注意,Image IO API让你知道哪种图象格式是支持的,并且你能设置例如压缩质量的参数。对于自定义文件对话框也将需要这些性质。

  loadImage()方法读取一个图片文件,路径是由命令行第一个参数提供的,并且设置主要panel的背景图片:

private void loadImage() {
if (args.length >= 1)
try {
File file = new File(args[0]);
BufferedImage image = ImageIO.read(file);
mainPanel.getPaintView().getModel().setBackImage(image);
} catch (IOException x) {
log(x);
}
}

  saveImage()方法获得一个主要panel的注释过的图片,并且把这个图片保存到一个文件里,路径是由命令行提供的第二个参数给出的:

private void saveImage() {
 if (args.length >= 2)
 try {
  File file = new File(args[1]);
  String name = file.getName();
  int k = name.lastIndexOf('.') + 1;
  String ext = name.substring(k);
  BufferedImage image= mainPanel.getAnnotatedImage();
  ImageIO.write(image, ext, file);
 } catch (IOException x) {
  log(x);
 }
}

 

 

做技术决定

  在开发过程中,我不得不去解决一些技术问题并且要做一些技术决定。下面的代码片段仅仅简单的进行了解释,但是他们将在我以后的文章中被详细描述。在这里重要的是去理解原型充当的角色。用你的原型去寻找技术问题的解决方案,去测试不常用的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类的完整代码将在以后的文章中讲述。上面代码片段仅仅展示了怎么利用原型去做技术决定。

  总结

  原型在应用程序开发过程中有着重要的角色,允许你测试你的想法并且尽早的获得用户反馈。我没有把原型看成是当“真正”开发开始时可以被丢弃的代码片段。反而,原型应该是你产品或者着应用的基础。这意味着你应该小心的对它进行编码,尽管你的类或方法在以后要被重写。

 

 

 

 

分享到:
评论

相关推荐

    搭建Java桌面应用程序原型

    【搭建Java桌面应用程序原型】是关于使用Java技术构建桌面应用早期阶段的工作,即创建一个功能简化的模型,以便评估技术可行性、验证用户需求并预估项目时间和资源。这篇文章由odt团队在2006年发表,以一个名为...

    day001 JAVA语法基础-JAVA环境搭建&第一个java程序.doc

    【Java环境搭建与第一个Java程序】 Java环境搭建是学习Java编程的第一步,它涉及安装Java Development Kit (JDK)和配置环境变量。JDK是Java编程的基础,包含了编译器、Java运行时环境以及各种Java工具。安装JDK时,...

    Java swing 桌面软件 学生选课系统 | 毕业设计 | 源码

    这个学生选课系统是一个完整的案例,涵盖了Java Swing GUI设计、数据库操作、用户认证和授权等多个方面的知识,对于学习Java桌面应用开发的初学者来说,是一个很好的实践项目。通过分析和理解这个系统,可以深入学习...

    a1.0-client-demo.rar

    本文将深入探讨一个名为"a1.0-client-demo"的Java桌面应用程序快速开发框架,它为开发者提供了便捷的数据管理功能,包括数据列表展示、表单设计以及数据的增删查改操作。 首先,"a1.0-client-demo"的核心价值在于它...

    快速原型设计工具

    6. **适配多平台**:Axure RP支持创建适应各种设备的原型,包括桌面、移动和Web应用。设计师可以设定不同屏幕尺寸和分辨率,确保跨平台的兼容性。 7. **版本控制**:对于大型项目,Axure RP的版本控制系统能够帮助...

    C++,C#,Java,Python实现简单的图形用户界面的区别和方法

    Windows Forms是一套完整的GUI开发框架,提供了丰富的控件集和工具支持,非常适合快速构建桌面应用程序。 **开发流程:** 1. **环境搭建**:使用Visual Studio作为开发环境。 2. **UI设计**:通过拖拽控件的方式...

    JAVA语言第13讲

    在Java中,我们可以使用各种工具和技术来实现PB,例如JavaFX或Swing用于创建桌面应用的交互原型,或者使用Spring Boot快速搭建服务端应用的雏形。通过PB,开发者能够更快地迭代和优化产品,降低开发风险,提高用户...

    适用于桌面开发的JSONRPC框架

    本项目"适用于桌面开发的JSONRPC框架"提供了一个原型实现,旨在集成JSONRPC协议和JSON反序列化功能,帮助开发者快速构建桌面应用的通信基础设施。以下是对这个框架的关键知识点的详细解析: 1. **JSONRPC协议**:...

    三子棋游戏java源码

    2. **图形用户界面(GUI)**:本项目可能使用了Java的`javax.swing.JFrame`来创建游戏界面,这是Java Swing库的一部分,用于构建桌面应用程序的窗口。`Frame`标签暗示了这一点。开发者可能还使用了`JButton`、`...

    Java+Swing+Txt实现宠物管理系统

    Java Swing 是Java GUI(图形用户界面)开发的一个关键库,它是Java Foundation Classes (JFC) 的一部分,提供了丰富的组件和接口来创建桌面应用程序。在这个"Java+Swing+Txt实现宠物管理系统"中,开发者利用了Swing...

    JFrame应用开发平台.zip

    JFrame是Java Swing库中的一个核心组件,它是Java桌面应用程序的基础框架。在Java GUI编程中,JFrame充当了窗口的主要容器,可以在这个框架上添加各种组件来构建用户界面。本项目"JFrame应用开发平台"显然是一个基于...

    一个简单的java五子棋

    在提供的【压缩包子文件的文件名称列表】中,"gobang.jar"很可能包含了整个五子棋游戏的可执行文件,这是一个Java应用程序的打包形式,可以直接运行。而"image"目录可能包含游戏中使用的图像资源,比如棋盘背景、...

    JAVA源码+openfire+spark 即时通讯

    结合JAVA源码、openfire和spark,开发者可以快速搭建起一个完整的即时通讯环境,并进行二次开发以适应特定业务需求。源码的学习可以帮助理解即时通讯系统的架构和工作原理,openfire和spark则提供了现成的基础设施,...

    网上商城页面原型HTML

    在测试阶段,原型需经过响应式测试,确保在不同设备(手机、平板、桌面电脑)上都能良好显示;同时,兼容性测试也很关键,要确保在主流浏览器如Chrome、Firefox、Safari等中都能正常运行。此外,性能优化也是重要一...

    ace界面原型

    【ace界面原型】是一款专为后台管理系统设计的模板,它以高效的Java技术为基础,结合了流行的Ace框架,为开发者提供了一套完整的、易用的、功能丰富的界面设计方案。这款模板适用于构建各种企业级后台应用,旨在提升...

    基于Java实现的学生信息管理系统的构建指南

    适用人群:具有一定Java编程经验并希望拓展对Maven项目管理和桌面应用开发技能的研发人员。 使用场景及目标:适用于教育机构或个人快速实现简易数据库管理原型的设计开发者。通过对本指南的学习,使用者能够熟练掌握...

    javafx-rest-archetype-1.1.zip

    JavaFX REST Archetype 1.1 是一个开源项目,它为开发者提供了一个Maven原型,目的是简化基于JavaFX和REST技术构建客户端-服务器应用程序的过程。这个压缩包文件"javafx-rest-archetype-1.1.zip"包含了项目的核心源...

    archetypes:一组有用的原型

    Maven RCP项目则是一种特殊类型的Java项目,它通常用于开发桌面应用程序,这些应用具有丰富的用户界面,可以利用Eclipse RCP(Rich Client Platform)框架。 在提供的压缩包文件名"archetypes-master"中,“master...

    提供基于baetyl-gateway软网关南向协议开发的SDK,包括Go、C#、Java、Python的实现.zip

    SDK是一组工具、库、文档和示例代码,帮助开发者快速构建应用程序。这里的SDK包含了上述四种编程语言的实现,使得开发者能够在各自熟悉的环境中实现对`baetyl-gateway`的南向接口的调用和扩展。 4. **Go SDK** Go...

    C#程序设计实训项目1.0

    这个实训项目分为四个步骤,第一步就是界面设计,这对于初学者来说是一个至关重要的起点,因为一个良好的用户界面是任何应用程序成功的关键因素。 1. **C#简介**: C#是一种面向对象的编程语言,由微软公司开发,...

Global site tag (gtag.js) - Google Analytics