1. 引言
在进行工程开发时,通常需要在窗口的某个区域将有效数据形象化地呈现出来,例如:对于某一区域的高程数据以伪色彩的方式呈现出高度的变化,这就需要解决利用Java进行数据呈现的问题。本文将建立新工程开始,逐步地介绍利用容器实现数据呈现的方法。
2. 建立新工程
在Esclipse中选择菜单:File-->New-->Project
在弹出的对话框中,选择Java Project
随后,在新的窗口中设置工程名称与工程存储位置
在这里需要说明的是,一般情况下,工程的存储位置不建议使用缺省位置,建议根据自己的实际情况,指定工程存储的路径,这样有利于后期对工程文件的管理与维护。
工程设置好后,在Eclipse中会呈现下图形式,在Eclipse的左侧将新工程以目录形式呈现。
通过文件资源管理器,可以在电脑的软件系统中找到如下目录。后期编写的软件都会存储在这个目录的相应子目录中。也可以在这个目录内建立本工程独特的目录,用于对某些特殊类型文件的管理。
至此,一个新的工程框架已经构建,但其内尚无任何可编辑的代码,此时需要建立相应的类文件,以便构造出程序的入口。
右击工程PaintPic下的src目录,在弹出鼠标菜单中选择:New --> Class
设置类文件的名称
注意,这里的Source folder建议采用其默认值,不需要修改。
将新的类文件PaintMain加入工程后,该文件名称会出现在src目录下的缺省包内,同时在编码窗口也将该文件打开,可以进行编辑。
此时,在电脑的文件系统中,工程目录中的src子目录下会出现文件PaintMain.java
在建立类文件时,可以发现文件PaintMain.java被放置在工程的缺省包内。当进行一个较复杂项目的开发时,工程中会涉及大量的java文件,为了能够对文件进行分类管理,通常需要根据文件的分类建立不同的包,并将相应的文件放置在包内。
建立新的包。右击src目录,在弹出的鼠标菜单中选择:New --> Package
在弹出的窗口中,给出包的名称
同样,这里的Source folder建议采用其默认值,不需要修改。
点击完成后,会在工程PaintPic的src目录下生成一个新的包MainPackage
同时,在电脑的文件系统中,在工程PaintPic目录的src子目录下会生成一个名为MainPackage的新子目录。
建立新的包后,可以直接将java文件拖到包内,也可选择右击包,建立新的类文件。
至此,一个工程的基本架构已经设置完成,后续将进行代码的编写。
3. 编写窗口文件
首先设置程序入口,在PaintMain类中增加代码
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
PaintMain window = new PaintMain();
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
代码中的PaintMain window = new PaintMain();指向程序PaintMain()。
在PaintMain()中进行窗口信息的设置。
public PaintMain() {
// 设置应用的主窗口
JFrame frame = new JFrame();
// 设置窗口位置及大小
frame.setBounds(0, 0, Toolkit.getDefaultToolkit().getScreenSize().width, Toolkit.getDefaultToolkit().getScreenSize().height);
// 将窗口最大化
frame.setExtendedState(JFrame.MAXIMIZED_BOTH);
// 设置窗口关闭时即退出工程
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
// 设置窗口可见
frame.setVisible(true);
// 设置背景容器
JPanel contentPane = new JPanel();
contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
contentPane.setLayout(null);
contentPane.setSize(frame.getContentPane().getSize());
frame.setContentPane(contentPane);
}
在PaintMain()中,首先设置框架frame的相关参数,随后在框架frame中设置背景容器contentPane。注意,在框架中一定要有容器,后续的所有内容都需要以这个背景容器为基础建立。
此时,运行代码即可获得一个空白的窗口。
有了窗体后,我们需要在这个窗体的指定区域将有效数据可视化。这个区域也需要用容器来处理,因此,建立新的类Backgnd用于生成相应的容器。
public class Backgnd extends JPanel {
public Backgnd() {
// 设置JPanel的宽与高
int width_JPanel = 1000;
int height_JPanel = 1000;
this.setSize(width_JPanel, height_JPanel);
// 设置JPanel的左上角位置
this.setLocation(30, 50);
// 设置JPanel的背景颜色
this.setBackground(Color.RED);
}
}
在这个类中,定义了容器的宽度、高度(以像素为单位)、其左上角的位置、及背景颜色。
在Backgnd中完成对容器的设置后,还需要在PaintMain中将Backgnd类声明,并加入到背景容器contentPane中。
public PaintMain() {
// 设置应用的主窗口
JFrame frame = new JFrame();
// 设置窗口位置及大小
frame.setBounds(0, 0, Toolkit.getDefaultToolkit().getScreenSize().width, Toolkit.getDefaultToolkit().getScreenSize().height);
// 将窗口最大化
frame.setExtendedState(JFrame.MAXIMIZED_BOTH);
// 设置窗口关闭时即退出工程
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
// 设置窗口可见
frame.setVisible(true);
// 设置背景容器
JPanel contentPane = new JPanel();
contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
contentPane.setLayout(null);
contentPane.setSize(frame.getContentPane().getSize());
frame.setContentPane(contentPane);
// 定义并加载地图显示窗口
Backgnd backPanel = new Backgnd();
// 将地图窗口加入到背景容器中
contentPane.add(backPanel);
}
再次运行工程,其效果如下:
由运行的结果可以看出,在工程窗体的左上部区域出现了一块红色背景的方块,这就是将来用于可视化数据的区域。
4.生成数据文件,并将其可视化
首先产生一组数据,数据的尺寸应与容器Backgnd的尺寸相当。确保每个像素点与数据中的每一位一一对应。
public static int[][] GenerateData(int width_Image, int height_Image){
int[][] imageData = new int[width_Image][height_Image];
double omega = Math.PI*2/500;
for (int w = 0; w < width_Image; w++){
for (int h = 0; h < height_Image; h++){
imageData[w][h] = (int) (500*Math.sin(omega * w)*Math.cos(omega * h));
}
}
return imageData;
}
这里是生成一个简单的波动数据。在实际中,这里应该是有效数据的整合代码。
随后,需要将数据转换为可进行图像显示的BufferedImage格式。
public static BufferedImage DrawImageBackground(int width_Image, int height_Image, int[][] imageData) {
BufferedImage imageBackground = new BufferedImage(width_Image, height_Image, BufferedImage.TYPE_INT_RGB);
// 获取数据中的最大值与最小值
int d_max = 0;
int d_min = 0;
for (int wn = 0; wn < width_Image; wn++){
for (int hn = 0; hn < height_Image; hn++) {
d_max = Math.max(d_max, imageData[wn][hn]);
d_min = Math.min(d_min, imageData[wn][hn]);
}
}
// 为数据点赋颜色
float r, g, b, temp;
for (int wn = 0; wn < width_Image; wn++){
for (int hn = 0; hn < height_Image; hn++) {
// 颜色图设置
temp = ((float) (imageData[wn][hn] - d_min)) / ((float) (d_max - d_min));
r = temp;
g = 1-temp;
b = (float) (Math.sin(2*Math.PI*temp)*0.5 + 0.5);
// 将颜色赋值给数据点
imageBackground.setRGB(wn, hn, new Color(r, g, b).getRGB());
}
}
return imageBackground;
}
在转换的过程中,需要对数据逐点进行着色。由于颜色参数r、g、b的取值范围是[0,1],所以需要对数据的范围进行归一化,而后再根据不同的着色方案对参数进行赋值。
代码中,首先通过for循环实现对数据中最小值d_min与最大值d_max的提取。而后,再利用for循环逐一对各个数据点的值进行归一化。利用归一化的值,按着不同的着色方案设置相应的r、g、b值。
产生数据的程序GenerateData和将数据转换为特定格式的程序DrawImageBackground可以放置在同一个类文件内。
至此,可以将上述两程序加载到Backgnd类中,以使得数据能够在相应的容器内呈现。
public class Backgnd extends JPanel {
BufferedImage imageBackground; // 初始化背景图
public Backgnd() {
// 设置JPanel的宽与高
int width_JPanel = 1000;
int height_JPanel = 1000;
this.setSize(width_JPanel, height_JPanel);
// 设置JPanel的左上角位置
this.setLocation(30, 50);
// 设置JPanel的背景颜色
this.setBackground(Color.RED);
int[][] imageData = DataProcess.GenerateData(1000, 1000);
imageBackground = DataProcess.DrawImageBackground(width_JPanel, height_JPanel, imageData);
}
public void paintComponent(Graphics g) { // 重载窗口组件的paint()方法
// 1.调用父类函数完成初始化任务
// 这句话不能少
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2.drawImage(imageBackground, 0, 0, this);
}
}
运行工程,得到下面的结果。
此至,完成了数据矩阵可视化的全部任务。
5. 结束语
本文只是给出了一个简单的数据矩阵可视化的例程,根据工程的实际情况,可以修改数据生成代码,着色代码等,形成工程所需的形式。