? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?画图板初步
? ?从只是一个窗口,到画图板各种组件一步一步的齐全。先说一下我最大的收获,也是以后要注意的。
一:设定参数变量的时候,变量名一定要起好,要有规律...不然的话自己都很难找。
二:传值的时候一定要小心,(例如在界面和监听器中传值),漏传,传错等,皆是空值。
?
?
?
心得总结:
?
通过这次的画图板,让我初步体会到了 做一个大的程序的一些经验。
?
以前学的只是一个个小的程序,变量不多,但是真正的大程序,数据繁琐,必须要做到每一步的清晰(尤其是我错了n次的传值)。
?
其次,一定要把同一部分的内容放在一起,不然会使程序显得十分凌乱不堪,一旦出错,会花上更多的精力去寻找。
?
最后,是关于空指针和空值的处理。
?
最有用的方法,无非就是一行一行的打印,当然,当我们遇到没用过不理解的方法的时候,也是要用到打印的方法去理解。
?
我所遇到的空值,主要是两种错误:
?
1:传值的时候出错。
2:声明了多次,无法识别。
?
?
下面,开始就自己的体会,详细分析画图板。
我的画图板,是就windows自带的画图板进行模仿。windows自带画图板,主要有以下几个部分组成,我们可以将其分区,分为centre,left,foot三个部分。其中,centre主要是画板以及背景,left主要是形状的工具条,而foot就比较复杂,有颜色的工具条,以及坐标。(这里是主要部分,其他小附件先略过)
?
主要分为画图板部分和重绘保存部分
?
先来画图板部分
?
创建界面,代码如下:
?
public class Draw extends JFrame {
	/**
	 * drawlistener要在第一个class中声明 创立监听器对象
	 */
	Drawlistener drawlistener;
	// 主函数
	public static void main(String args[]) {
		// 创建窗体对象,打开画板对象,固定格式
		Draw draw = new Draw();
		draw.draw1();
	}
	/**
	 * 初始化窗体
	 */
	public void draw1() {
		this.setTitle("画图板");
		this.setSize(600, 500);
		this.setBackground(java.awt.Color.gray);
		// 居中显示
		this.setLocationRelativeTo(null);
		// 关闭方式
		this.setDefaultCloseOperation(3);
		// 设置画板的布局格式
		// 切记BorderLayout是java.awt.BorderLayout下面的要在前面引入
		BorderLayout borderlayout = new BorderLayout();
		this.setLayout(borderlayout);
?
这样就初步做好了我们的登陆界面
?
这里要注意的是,1,最好要居中显示,不然自动默认到左上角。2,记得要有关闭方式,不然仍然存在在系统内存里面。3,记得要设置布局模式,在此处,我用的是BorderLayout。4,主函数主要起得是一个引入的作用里面不要放太多的东西。
?
再来简单介绍下BorderLayout:
?
这是一个布置容器的边框布局,它可以对容器组件进行安排,并调整其大小,使其符合下列五个区域:北、南、东、西、中。每个区域最多只能包含一个组件,并通过相应的常量进行标识:NORTH、SOUTH、EAST、WEST、CENTER。当使用边框布局将一个组件添加到容器中时,要使用这五个常量之一,例如: 
    Panel p = new Panel();
    p.setLayout(new BorderLayout());
    p.add(new Button("Okay"), BorderLayout.SOUTH);
?
?
设置下左边的工具条:
?
/** * 开始工具条 左边 */ // 创建左边的工作条,默认是水平的,我们此处要改成垂直的--vertical javax.swing.JToolBar left = new javax.swing.JToolBar( javax.swing.JToolBar.VERTICAL); // 创建尺寸对象 记着要设计其长宽 java.awt.Dimension dimension1 = new java.awt.Dimension(70, 400); // 设置大小 其传入的值是对象,所以传入dimension1 left.setPreferredSize(dimension1); // 加在画板上面 this.add(left, BorderLayout.WEST);
这里加在画板上的时候,要小心是在WEST~~
?
对比windows画板可知,左边的工具条是有很多按钮的,于是,我们在左边工具条上加一个buttongroup,并且设置布局,如代码所示:
?
left.setLayout(new FlowLayout(FlowLayout.CENTER, 0, 0)); // 按钮分组 javax.swing.ButtonGroup group = new ButtonGroup(); // 大小 Dimension dimension2 = new Dimension(30, 30);
?这里将其布局设置为流式布局~
下面,加按钮:
?
                // 直线的
		// 加单选按钮
		 JRadioButton line = new JRadioButton("直线");
		// 设置其动作命令
		 line.setActionCommand("line");
		// 设置默认选中
		line.setSelected(true);
		// 放在组里面
		 group.add(line);
		 left.add(line);
		// 矩形~
		 JRadioButton rectangle = new JRadioButton("矩形");
		 rectangle.setActionCommand("rectangle");
		// 放在组里面
		 group.add(rectangle);
		 left.add(rectangle);
		
?
?
这里我只贴出直线和矩形的,其他的方法一样,复制即可,就不贴出来了~~
需要注意的是,要有个默认选中,我的默认选中是直线。
?
?
下面是centre的部分。
中间要创建两个Jpanel,先是背景的,要注意设置其背景颜色为灰色,不要忘了,还有要记得布局是centre
?
// 创建中间的panel javax.swing.JPanel cjp = new JPanel(); // 设置中间的背景颜色 cjp.setBackground(java.awt.Color.gray); // 加在画板上 都是borderlayout的 this.add(cjp, BorderLayout.CENTER);
?再来是画板的
?
/** * 给中间加绘制的面板 jpanel */ // 设置布局 流式中间左对齐 FlowLayout center = new FlowLayout(FlowLayout.LEFT); this.setLayout(center); // 创建面板对象 javax.swing.JPanel jp = new Panel1(); // 设置大小 jp.setPreferredSize(new Dimension(450, 350)); // 设置背景颜色 jp.setBackground(java.awt.Color.WHITE); // 加 cjp.add(jp);?
注意:1,要设置为左对齐。2,背景颜色为白色。
?
下面是底部
由于底部由两部分组成,颜色的工具条和坐标,因此我们要在底部设置一个Jpanel
?
?
javax.swing.JPanel southjp = new javax.swing.JPanel(); // 设置底部面板的大小 southjp.setPreferredSize(new java.awt.Dimension(100, 60)); // 加在画板上面 this.add(southjp, BorderLayout.SOUTH); // 设置底部面板的布局 southjp.setLayout(new BorderLayout());?
?
底部的颜色条因为和形状的工具条基本相同,就不贴代码了~
?
然后就是坐标滴,坐标也是一个Jpanel~,上面主要显示为两部分~
1:坐标移动的显示
2:显示出画图二字
?
// 再设置一个jpanel...
		javax.swing.JPanel zhuangtailan = new javax.swing.JPanel();
		// 设置底部面板的大小
		zhuangtailan.setPreferredSize(new java.awt.Dimension(600, 30));
		// 设置背景色
		zhuangtailan.setBackground(java.awt.Color.white);
		// 加在画板上面
		southjp.add(zhuangtailan, BorderLayout.CENTER);
		// 加label label,标签
		JLabel left1 = new JLabel("画板");
		JLabel center1 = new JLabel("");
		JLabel right = new JLabel("");
		// 加在zhuangtailan(jpanel)
		zhuangtailan.add(left1);
		zhuangtailan.add(center1);
		zhuangtailan.add(right);
?
最后一步 就是传值和显示~~
传值这里要格外小心,要传入的值有graphics, center1, group1, group
且在监听器出要一一对应
?
// 显示 this.setVisible(true); // 这些要放在setvisible之后~! // 从jp上获取画布对象 java.awt.Graphics graphics = jp.getGraphics(); // 创建监听器对象 // 在第23行已经定义了drawlistener,这里就不需要再定义,不然会 出现空值 drawlistener = new Drawlistener(graphics, center1, group1, group); // 给jp加鼠标监听器 jp.addMouseListener(drawlistener); jp.addMouseMotionListener(drawlistener); }?
其余注释以及注意事项皆在代码里面
?
?
监听器
?
?
监听器要继承MouseListener, MouseMotionListener 两个接口
注意要实现接口中的所有方法
同时,一定要声明以及定义,具体如代码:
?
public class Drawlistener implements MouseListener, MouseMotionListener {
	// 定义x1,x2,y1,y2
	private int x1, x2, y1, y2;
	// 声明Graphics 是画直线的~画图~
	private java.awt.Graphics g1;
	// 声明ButtonGroup
	// 颜色的
	private javax.swing.ButtonGroup color_group;
	// 形状的
	private javax.swing.ButtonGroup group;
	// line,RoundRect;rectangle
	private String type = "line";
	private String type1 = "black";
	// 声明JLabel
	private javax.swing.JLabel centerjl;
?
?
接下来是传值
传值的时候一定要小心~~
不然会空值!!!!!!!!这里出错了n次~
?
// 说明下Graphics g1,JLabel centerjl,ButtonGroup gl, ButtonGroup group
	public Drawlistener(java.awt.Graphics g1, javax.swing.JLabel centerjl,
			ButtonGroup gl, ButtonGroup group) {
		// 传值
		// 设数值的时候一定要要小心啊
		this.g1 = g1;
		this.color_group = gl;// 传入选择颜色的group
		this.group = group;// 传入选择图形的group
		// 记得把JLabel的值传过来 不然又是空指针
		this.centerjl = centerjl;
?
下面主要就是方法
先来介绍下MouseListener, MouseMotionListener 两个接口的方法以及我们所需要的
MouseListener:
方法摘要 void
mouseClicked(MouseEvent e) 
 void
mouseEntered(MouseEvent e) 
 void
mouseExited(MouseEvent e) 
 void
mousePressed(MouseEvent e) 
 void
mouseReleased(MouseEvent e) 
?
MouseMotionListener:
?
方法摘要 void
mouseDragged(MouseEvent e) 
 void
mouseMoved(MouseEvent e) 
?
?
?
其中,我们主要用到的方法有:
?
?mousePressed(MouseEvent e){颜色 吸管}
?mouseReleased(MouseEvent e) {形状,重绘保存}
?mouseMoved(MouseEvent e), mouseExited(MouseEvent e)?{坐标的移动}
?
剩下的三个方法放在后面即可,不用~~
?
颜色 ,形状差不多
下面就贴出形状的代码
?
/**
		 * 形状
		 */
		// 在绘制前获取
		
		javax.swing.ButtonModel buttonmodel = group.getSelection();
		// 得到按钮模型的动作命令
		type = buttonmodel.getActionCommand();
		System.out.println(type);
		// 得到鼠标按下时候的光标的坐标 用x1,y1来表示相对于画布
		x1 = e.getX();
		y1 = e.getY();
	/**
	 * mouseReleased 鼠标释放 主要是画形状和截图保存
	 */
	public void mouseReleased(MouseEvent e) {
		// 得到鼠标释放的时候光标的坐标用x2,y2来表示
		x2 = e.getX();
		y2 = e.getY();
		/**
		 * 画形状
		 */
		// 开始画~ 直线
		if (type.equals("10")) {
			// 这是是固定格式
			// 这里点的获取要小心~(x1,y1)
			g1.drawLine(x1, y1, x2, y2);
			
		}
		// 矩形
		if (type.equals("12")) {
			g1.drawRect(Math.min(x1, x2), Math.min(y1, y2), Math.abs(x1 - x2),
					Math.abs(y1 - y2));
			System.out.print(g1 + "reck");
		}
		// 圆角矩形
		if (type.equals("15")) {
			g1.drawRoundRect(Math.min(x1, x2), Math.min(y1, y2),
					Math.abs(x1 - x2), Math.abs(y1 - y2), 35, 35);
		}
		// 弧线
		if (type.equals("11")) {
			g1.drawArc(x1, y1, 200, 200, 150, 150);
		}
?
这里可以看到,我type.equals后面跟的不是前面定义的变量名,这个会在后面解释,主要是牵涉到我们把按钮变成和windows画图板一样的图标
?
、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、
?
?
下面是重绘部分
?
重绘有两种方法。
?
一:队列
二:数组:1:二位数组
? ? ? ? ? ? ? ?2:直接截图保存
但是,如果我们想把数据储存在硬盘里面,只能用二位数组的保存方法
?
?
下面详解用二维数组的保存方法
?
?
在界面里:
?
?
现在主函数里面声明drawlistener
接着 我们在写一个class
也即嵌套一个class
代码如下
?
class Panel1 extends javax.swing.JPanel {
		/**
		 * 
		 */
		private static final long serialVersionUID = 1L;
		// 重写绘制方法
		// 当改变时自动调用
		// 重写paint,参数从ava.awt.Graphics graphics 调用
		public void paint(java.awt.Graphics graphics) {
			// 调用父类方法 此时不可用this 要用super
			super.paint(graphics);
			// if循环
			// 在监听器中创建的二维数组
			// drawlistener,drawlistener.keep不是空值的时候进入循环
			if (drawlistener != null && drawlistener.keep != null) {
				// 遍历
				
				for (int i = 0; i < drawlistener.keep.length; i++) {
					for (int j = 0; j < drawlistener.keep[i].length; j++) {
						// 取颜色
						int cNum = drawlistener.keep[i][j];
						// 若储存颜色变 了,就在绘制一次
						if (cNum != this.getBackground().getRGB()) {
							// 数字转颜色~强制转型
							Color color = new Color(cNum);
							// 绘制点
							graphics.setColor(color);
							graphics.drawLine(j, i, j, i);
						}
					}
				}
			}
		}
	}
}
?
?
1:这里的原理,就是把整幅图保存在内存里面,依据是其颜色的改变
2:关键字这里不可再用this,要用super~
?
下面是监听器
?
首先,声明保存的二维数组,在创建一个robot对象
?
*/ // 声明保存的二维数组(绘制区域) int[][] keep; // 声明robot java.awt.Robot robot;?
robot要写在public drawlistener里面
添加后代码如下
?
public Drawlistener(java.awt.Graphics g1, javax.swing.JLabel centerjl,
			ButtonGroup gl, ButtonGroup group) {
		// 传值
		// 设数值的时候一定要要小心啊
		this.g1 = g1;
		this.color_group = gl;// 传入选择颜色的group
		this.group = group;// 传入选择图形的group
		// 记得把JLabel的值传过来 不然又是空指针
		this.centerjl = centerjl;
		// robot
		/**
		 * 报错出现Unhandeled Exception...要加上try{}catch{} 这里就是个格式~
		 */
		try {
			
			robot = new java.awt.Robot();
		} catch (Exception ef) {
			ef.printStackTrace();
		}
	}
?
?
1:try...catch是固定的格式
2:关于报错 如果出现Syntax error on token(s)...表示要加()
?
主要写在mouseReleased(MouseEvent e)里面 具体代码如下
?
?
		Object object = e.getSource();
		// object一定是中间绘制的面板将jpanel对象---jp~
		javax.swing.JPanel jp = (javax.swing.JPanel) object;
		// 得到jp左上角坐标,获取相对屏幕的坐标
		java.awt.Point leftpoint = jp.getLocationOnScreen();
		// 得到宽度 高度
		java.awt.Dimension dimension1 = jp.getPreferredSize();
		// 创建截取的区域对象,以jp左上角为起点,jp的大小
		// 区域对象是长方形 所以用rectangle
		java.awt.Rectangle rectangle = new java.awt.Rectangle(leftpoint,
				dimension1);
		// 截图
		java.awt.image.BufferedImage image = robot
				.createScreenCapture(rectangle);
		/**
		 * 创建二维数组
		 */
		keep = new int[image.getHeight()][image.getWidth()];
		// 写两个for循环
		for (int i = 0; i < keep.length; i++) {
			for (int j = 0; j < keep[i].length; j++) {
				// 获取图像对应坐标点颜色,储存在数组中,对应的下标位置
				/**
				 * 这里要小心 联系线代 i=y,j=x 不然就会弄反
				 */
				keep[i][j] = image.getRGB(j, i);
			}
		}
	}
?
?
1:i=y,j=x,这里一定要注意!
2:截图只要是截的是矩形的区域
?
这样~~我们基本的架构已经做完啦~~
?
最后一步,就是美化一下~~
将按钮变成图标
主要也是用数组
?
?
首先,先要截好图~~(按钮的图片)
在将其放在代码所在的文件夹下面
?
先屏蔽掉以前的
新代码如下~
?
String[] commands = { "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "15", "16" }; for (int i = 0; i < commands.length; i++) { // 单选按钮 JRadioButton shape = new JRadioButton(); // 设置大小 // 小心这里传值又别弄错了!!! shape.setPreferredSize(dimension2); // 设置内边距 shape.setMargin(new java.awt.Insets(0, 0, 0, 0)); // 因为鼠标按下时候有4种形态 // 创建4个图标ImageIcon---图标对象 javax.swing.ImageIcon image1 = new javax.swing.ImageIcon( "images/draw" + i + ".jpg"); javax.swing.ImageIcon image2 = new javax.swing.ImageIcon( "images/draw" + i + "-1.jpg"); javax.swing.ImageIcon image3 = new javax.swing.ImageIcon( "images/draw" + i + "-2.jpg"); javax.swing.ImageIcon image4 = new javax.swing.ImageIcon( "images/draw" + i + "-3.jpg"); // 设置4种形态 shape.setIcon(image1); shape.setRolloverIcon(image2); shape.setPressedIcon(image3); shape.setSelectedIcon(image4); // 动作命令 shape.setActionCommand(commands[i]); if (i == 6) shape.setSelected(true); // 放进组 group.add(shape); // 加在左边的工具条上 left.add(shape); }?
?
现在,知道我前面监听器里面的11等数字的代表了吧~~~
?
?
画图板总体的架构已经完成,剩余的,就是其他功能的实现~~
?
?
?
?
 相关文章
                            相关文章