在学习java的这段时间里,我运用所学的知识,制作了应该算是本人的第一个产品——画板。
在总结制作经验之前,我想先进行所运用到的知识的总结:
知识总结:
1、Java的图形界面
1.awt
包名:java.awt
awt的组件称之为重量级组件
2.swing
包名:javax.swing
基于awt构建一套轻量级组件,swing中的顶级容器还是重量级组件
(可通过添加: import java.awt.组件名 和 import javax.swing.组件名 的方式,避免 javax.swing和java.awt在代码中的反复出现)
2 .常用的组件类
1.容器组件类:能添加其他的容器组件或者元素组件的类就是容器组件类
JFrame 窗体容器组件类 顶级容器
2.元素组件类:一般是用来显示文字、图片或者接收输入的组件类就是元素组件类
JLabel 标签元素组件类 显示文字、图片
JTextField 文本输入框元素组件类 接收输入,直接显示
JPasswordField 密码输入框元素组件类 接收输入,以某个符号代替显示
JCheckBox 复选框元素组件类 提供一个选择框让用户选择,还能显示文字、图片
JButton 按钮元素组件类 显示文字、图片,还可以点击
上述的容器组件和元素组件类都是javax.swing包下的类
如果要使用awt的组件,包名必须是java.awt,类名必须swing的类名要少一个字母J:JFrame -- Frame
3.辅助类:帮助容器组件或者元素组件完成某一个功能的类
ImageIcon 图标类 加载一张图片到程序中 是javax.swing包下的类
Dimension 封装宽高类 封装组件的宽度和高度 是java.awt包下的类
FlowLayout 流式布局类 针对容器的,设置容器上所添加组件的排列对其方式 是java.awt包下的类
经验总结:
制作这个产品,我渐渐感受到了一个完善的产品需要背后多少程序员不断的修改代码。
制作一个产品之前,最好先进行一番规划,不要想到什么就打什么代码,导致代码架构凌乱。
就如我的画板项目,a、写出一个可以显示的界面,设置相应属性
b、在界面添加相应按钮、文本框
c、实现事件监听接口,并添加到相应事件源上
d、为实现了事件监听接口的类添加方法,属性
e、想要添加新功能:重复b、c、d
我的画板项目的完成思路大致如此。
项目难点:1、类型的转化,
每当想要在程序中传递一些特别的东西时,系统总是会给出类型不匹配的错误或者出现并不想要的东西。
如:1、绘制一张图片 ImageIcon类要转换成 Image类
ImageIcon image = new ImageIcon(this.getClass().getResource("0001.JPG"));
Image I=image.getImage();
g.drawImage(I, x1, y1, 100, 100, Color.GREEN, this);
2、使用1、方法不能绘制动态图片(不显示任何东西)
3、从界面设置数值大小 JTextField框中的string类要转换成int类
private JTextField textName;
int large=Integer.parseInt(this.textName.getText());
2、设置窗体背景
设置图片:
public void setBackgroundImage(JFrame f){
ImageIcon bg = new ImageIcon(this.getClass().getResource("222.jpg"));
JLabel lbg = new JLabel(bg);
lbg.setBounds(0, 0,bg.getIconWidth(), bg.getIconHeight());
//获取JLayeredPane对象
JLayeredPane lp = (JLayeredPane)f.getLayeredPane();
//将labelBackground组件添加到JLayeredPane面板的最底层
lp.add(lbg, new Integer(Integer.MIN_VALUE));
//获取窗体的内容面板(组件就是添加到此面板上)
JPanel panel = (JPanel)f.getContentPane();
panel.setOpaque(false);//设置ContentPane为透明
}
设置颜色:
JPanel panel = (JPanel)this.getContentPane();
panel.setOpaque(false);//设置ContentPane为透明
this.setBackground(Color.WHITE);
3、重绘
当我们改变窗体大小时,在窗体上绘制的图形就会消失。重绘则是当我们改变窗体大小,将窗体上绘制的图形在线。
原理:存储绘图时的数据(可以是像素,也可以是绘图用的关键数据(坐标、颜色、图形种类)),重写需要重绘的界面的paint方法
我的方法:a、构造一个save类,并定义属性(坐标、颜色、图形种类)
b、在界面类中构造一个save数组,大小适中
c、在绘图的监听方法中,设置把数据依次存入save
d、在界面类中重写界面的paint方法,我的代码:
public void paint(Graphics g){
super.paint(g);//继承之前这个
for(int i=0;i<s.length;i++){
if(s[i]==null)break;
int xx[]={s[i].x1,s[i].x1+30,s[i].x1+50,s[i].x2,s[i].x2+10,s[i].x1};
int yy[]={s[i].y1,s[i].y1+30,s[i].y1+50,s[i].y2,s[i].y2+10,s[i].y1};
switch (s[i].shape)
{case"直线":g.drawLine(s[i].x1, s[i].y1, s[i].x2,s[i]. y2);
break;
case"矩形": g.drawRect(s[i].x1, s[i].y1, Math.abs(s[i].x1-s[i].x2),Math.abs(s[i].y1-s[i].y2));
break;
case"圆": g.drawOval(s[i].x1, s[i].y1, Math.abs(s[i].x1-s[i].x2),Math.abs(s[i].y1-s[i].y2));
break;
case"弧线": g.drawArc(s[i].x1, s[i].y1, Math.abs(s[i].x1-s[i].x2), Math.abs(s[i].y1-s[i].y2), Math.abs(s[i].x1-s[i].x2), Math.abs(s[i].y1-s[i].y2));
break;
case"填充矩形": g.fillRect(s[i].x1, s[i].y1, Math.abs(s[i].x1-s[i].x2), Math.abs(s[i].y1-s[i].y2));
break;
case"圆角矩形": g.drawRoundRect(s[i].x1, s[i].y1,Math.abs(s[i].x1-s[i].x2), Math.abs(s[i].y1-s[i].y2), 30, 30);
break;
case"填充圆角矩形": g.fillRoundRect(s[i].x1, s[i].y1,Math.abs(s[i].x1-s[i].x2), Math.abs(s[i].y1-s[i].y2),30, 30);
break;
case"3D矩形": g.draw3DRect(s[i].x1, s[i].y1,Math.abs(s[i].x1-s[i].x2), Math.abs(s[i].y1-s[i].y2),false);
break;
case"填充3D矩形": g.fill3DRect(s[i].x1, s[i].y1, Math.abs(s[i].x1-s[i].x2), Math.abs(s[i].y1-s[i].y2), false);
break;
case"填充弧线": g.fillArc(s[i].x1, s[i].y1, Math.abs(s[i].x1-s[i].x2), Math.abs(s[i].y1-s[i].y2), Math.abs(s[i].x1-s[i].x2), Math.abs(s[i].y1-s[i].y2));
break;
case"填充圆": g.fillOval(s[i].x1,s[i]. y1, Math.abs(s[i].x1-s[i].x2),Math.abs(s[i].y1-s[i].y2));
break;
case"多边形": g.drawPolygon(xx,yy, 6);
break;
case"填充多边形": g.fillPolygon(xx, yy, 6);
break;
case"字符": String name= s[i].textName.getText();
g.setFont(s[i].f);
g.drawString(name, s[i].x1, s[i].y1);
break;
case"图片": g.drawImage(s[i].I, s[i].x1, s[i].y1, 100, 100, Color.GREEN, this);
break;
}
}}
4、递归图形
也有叫分形的,我觉得这个更多的是在套公式,套对了图形就出来了。
凡递归或有规律的运算,一些偏差都会出现不一样的结果,这里我建议:
运算时使用double类型,而输出时使用(int)强制转换可减小误差。
使用doubl类型运算,用(int)强制转换输出的L-System
用int类型运算的L-System
可以看出后者图形的不稳定性高于前者。