您的位置:首页 > 移动开发 > 微信开发

Java小程序之高级画板功能篇I

2016-11-13 00:12 465 查看
Java小程序之高级画板功能篇I

前言:通过前面阶段的学习,已经学完了Java中的继承、重载、多态、构造函数、Java图形界面等知识,并结合一些小程序来加深对这些知识的理解;

          今天,在完成Java小程序之高级画板UI篇的基础上来实现一些画板的功能;根据选取的颜色绘制该种颜色直线、矩形、椭圆;

          用到的知识点:监听器的使用(鼠标监听)、对象传递(难点)

         堆栈知识图片(一定要仔细分析下面图,明白其中的原理,对代码测试结果一定要清楚的明白其中的原理)

         
          








画板功能篇I思路:

1、给左画板中的按钮组中的每个按钮添加鼠标监听器;
2、点击不同按钮,绘制不同的图形;(可以参考前面的简单画板入门)
3、给下面板中的每个颜色按钮添加鼠标监听器;
4、根据下面板中选中的颜色按钮,来获取按钮的背景颜色,并将该颜色设置成画笔的颜色;
5、根据下面板中选中的颜色按钮,来获取按钮的背景颜色,并将该颜色设置下面板中的左子面板中的按钮颜色,来提醒当前选中的是那种颜色

原代码:
DrawBorder类:
红色代码为新增代码:
package com.huaxin.zhou1;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Graphics;

import javax.swing.ButtonGroup;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JRadioButton;
import javax.swing.border.BevelBorder;
import javax.swing.border.Border;

public class DrawBorder extends JFrame{

//声明颜色属性,并赋默认值
public Color c=Color.RED;
//按钮属性,便于其他类访问
public JButton  bt ;

public void initFrame(){

//设置窗体相关属性
this.setSize(600,500);
this.setTitle("我的画板");
this.setDefaultCloseOperation(3);
this.setLocationRelativeTo(null);

//窗体添加主面板
JPanel panel = new JPanel();
panel.setLayout(new BorderLayout());
this.add(panel);

JPanel panelcenter = new JPanel();
panelcenter.setBackground(Color.white);
panel.add(panelcenter);

//主面板添加左面板
JPanel panelleft = new JPanel();
panelleft.setPreferredSize(new Dimension(50,0));
panelleft.setLayout(new FlowLayout(FlowLayout.LEFT,0,0));
panelleft.setBackground(new Color(235,233,238));
panel.add(panelleft,BorderLayout.WEST);

//面板中添加按钮
//按钮归类,统一管路
ButtonGroup bg = new ButtonGroup();
for(int i=0;i<16;i++){
JRadioButton jrb = new JRadioButton();

//给按钮添加图片
ImageIcon img1  = new ImageIcon("images/draw"+i+".jpg");
ImageIcon img2  = new ImageIcon("images/draw"+i+"-1.jpg");
ImageIcon img3  = new ImageIcon("images/draw"+i+"-2.jpg");
ImageIcon img4  = new ImageIcon("images/draw"+i+"-3.jpg");
jrb.setIcon(img1);
jrb.setRolloverIcon(img2);
jrb.setPressedIcon(img3);
jrb.setSelectedIcon(img4);
jrb.setBorder(null);
//设置默认选中的按钮
if(i==10){
jrb.setSelected(true);
}
jrb.setActionCommand("pic"+i);//设置按钮名称

bg.add(jrb);
panelleft.add(jrb);
}

//主面板添加下方面板
JPanel paneldown =new JPanel();
paneldown.setPreferredSize(new Dimension(0,60));
paneldown.setLayout(null);
paneldown.setBackground(Color.gray);
panel.add(paneldown, BorderLayout.SOUTH);

//下方面板添加子面板
JPanel paneldownchild = new JPanel();
paneldownchild.setBackground(Color.cyan);
paneldownchild.setLayout(new FlowLayout(FlowLayout.LEFT,0,0));
paneldownchild.setBounds(10,10,280,40);
paneldown.add(paneldownchild);

//按钮特效
BevelBorder bb = new BevelBorder(0, Color.gray,Color.white);
BevelBorder bb1 = new BevelBorder(1, Color.gray,Color.white);

JPanel left = new JPanel();
left.setBackground(Color.white);
left.setLayout(null);
left.setBorder(bb);
left.setPreferredSize(new Dimension(40,40));

//左面板中的两棵颜色按钮
bt = new JButton();
bt.setBounds(5, 5, 20, 20);
bt.setBorder(bb1);
bt.setBackground(Color.black);
bt.setSize(20,20);
JButton bt1 = new JButton();
bt1.setBorder(bb1);
bt1.setBounds(15,15,20,20);
left.add(bt);
left.add(bt1);

//右面板
JPanel right = new JPanel();
right.setBackground(Color.BLUE);
right.setLayout(new FlowLayout(FlowLayout.LEFT,0,0));
right.setPreferredSize(new Dimension(240,40));

paneldownchild.add(left);
paneldownchild.add(right);

//给右面板的颜色按钮天添加监听器,注意传递this对象
ButtonListener bl =new ButtonListener(this);//这里为什么传递的是this?请看后面的难点
//颜色数组,用来设置按钮的背景颜色
Color []colors = {new Color(0,56,67),new Color(89,3,14),new Color(189,3,14)
,new Color(89,93,14),new Color(89,113,14),new Color(89,73,14)
,new Color(89,3,14),new Color(89,3,14),new Color(29,83,14)
,new Color(89,3,184),new Color(189,233,14),new Color(89,253,14)
,new Color(89,93,14),new Color(89,89,94),new Color(1,3,14)
,new Color(9,83,94),new Color(89,178,147),new Color(9,33,164)
,new Color(34,23,14),new Color(89,173,154),new Color(8,193,194)
,new Color(9,253,76),new Color(89,240,104),new Color(199,73,4)};

//循环添加24个颜色按钮
for(int i=0;i<24;i++){
JButton bt3 = new JButton();
Color c=new Color(i*10,30-i,i*7+50);
bt3.setBackground(colors[i]);
bt3.setPreferredSize(new Dimension(20,20));
bt3.setBorder(bb);
bt3.addActionListener(bl);
right.add(bt3);
}

this.setVisible(true);

//画笔必须在setVisible后才能拿
Graphics g=panelcenter.getGraphics();//因为是在中间面板省绘制图形,所以画笔应该在中间画板上获取,那么同样,鼠标监听的应该也是中间画板

//传递画笔,按钮组管理对象,以及this对象
DrawListener dl =new DrawListener(g,bg,this);
panelcenter.addMouseListener(dl);

}
}


颜色按钮监听类:ButtonListener类

package com.huaxin.zhou1;

import java.awt.Color;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JButton;

//按钮监听类,实现ActionListenerde接口
public class ButtonListener implements ActionListener{

public DrawBorder db;

//构造函数
public ButtonListener(DrawBorder db1) {
db=db1;
}

//监听具体实现
public void actionPerformed(ActionEvent e) {

//拿到被选中按钮的对象
JButton bt =(JButton)e.getSource();
//拿到被选中按钮的背景颜色
Color c= bt.getBackground();
//把背景颜色复制给DrawBorder中的颜色属性
db.c=c;
//把左面板中的按钮颜色设置成选中按钮的背景颜色
db.bt.setBackground(c);

}

}


鼠标监听类:DrawListener类:

package com.huaxin.zhou1;

import java.awt.Color;
import java.awt.Graphics;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;

import javax.swing.ButtonGroup;
import javax.swing.ButtonModel;

public class DrawListener implements MouseListener{

public Graphics g;
public int x1,y1,x2,y2;
public ButtonGroup bg;
public String command;
public Color color;
public DrawBorder db;
//构造函数1
public DrawListener(Graphics g1){
g=g1;
}
//构造函数2

public DrawListener(Graphics g2, ButtonGroup bg2) {
g=g2;
bg=bg2;
}

//构造函数3
public DrawListener(Graphics g2, ButtonGroup bg2, DrawBorder db1) {
g=g2;
bg=bg2;
db=db1;
}

//获取鼠标按下的坐标
public void mousePressed(MouseEvent e) {
x1=e.getX();
y1=e.getY();

//判断选择的是左面板中的那个按钮被选中(前面已经设置每个按钮的名称了)
ButtonModel bm=bg.getSelection();//拿到按钮组中被选中的按钮
command=bm.getActionCommand();//拿到选中按钮的名字
color=db.c;//设置画笔颜色

g.setColor(color);
}

public void mouseReleased(MouseEvent e) {
//获取鼠标释放的坐标
x2=e.getX();
y2=e.getY();
//如果选中的是绘制直线的按钮,那么根据鼠标按下点的坐标和释放点的左边绘制直线(两点确定一条直线)
if("pic10".equals(command))
{
g.drawLine(x1, y1, x2, y2);
}//同理选中的是矩形按钮,那么绘制矩形(这里有绘制矩形的纠正,不纠正的话从右下角往左上角方向绘制矩形会出现问题,参看后面难点解析)
else if("pic12".equals(command)){
g.drawRect(Math.min(x2, x1),Math.min(y2, y1), Math.abs(x2-x1),Math.abs(y1-y2));
}//绘制椭圆
else if("pic14".equals(command)){
g.drawOval(Math.min(x2, x1),Math.min(y2, y1), Math.abs(x2-x1),Math.abs(y1-y2));
}

}

public void mouseClicked(MouseEvent e) {

}

public void mouseEntered(MouseEvent e) {

}

public void mouseExited(MouseEvent e) {

}

}


测试类:Test类

package com.huaxin.zhou1;

public class Test {

public static void main(String[] args) {
DrawBorder db = new DrawBorder();
db.initFrame();
}
}


运行结果:



请注意程序下面板中左边子面板中那颗白色按钮上面的颜色会随着你选中的颜色而变化,当前你选择的是什么颜色,那么那颗按钮就是什么颜色;

难点解析:
1、绘制矩形时的纠正问题(长宽为什么是绝对值,因为可能出现负数)
     如果我们使用
g.drawRect(x1,y1, Math.abs(x2-x1),Math.abs(y1-y2))

     绘制矩形时,x1,y1记录的是鼠标按下的坐标,此时,如果我们从右下角往左上角方西绘制矩形时(只有从左上角往右下角方西绘制矩形时正确的,其他三色方西会出现问题),绘制的是以x1,y1位左上角的点,长宽为Math.abs(x2-x1),Math.abs(y1-y2)往右下角绘制矩形,而不是往左上角绘制矩形,未来得到正确的矩形,我们只需比较x1,x2和y1,y2哪个最小,并以最小的值作为绘制矩形的左上角的那个点就不会出现问题了;

2、对象传递问题(难难难)
      2.1画笔是从DrawBorder中获取的,但是要在DrawLisrener中使用,这个时候我们可以利用DrawListener的构造函数,把属于DrawBorder中的画笔传递给DrawListener类中(该类中需要定义画笔类型的变量),根据前面的堆栈知识图,我们可以知道DrawListener中的画笔其实是DrawBorder中那只画笔的引用,即两个画笔变量(栈中)指向同一个画笔对象的(堆中),这就好比你把你的房间给了另一个人一把钥匙,另一个人也可以用你给的钥匙进入你的房间,拿你房间的东西使用;

       2.2怎么把ButtonListener类中获取的按钮颜色传递给DrawListener类进行使用呢?

          我们在DrawBorder类中声明了一个Color变量的属性,先把ButtonListener类中获取的按钮颜色传递DrawBorder类中的Color变量,这里我们需要在ButtonListener类中访问DrawBorder类中的某个属性,我们可以利用构造函数把当前DrawBorder对象传给ButtonListener类,这样ButtonListener类就能访问DrawBorder类中的所有属性和方法了(同样好比你把你的房间给了另一个人一把钥匙,另一个人也可以用你给的钥匙进入你的房间,拿你房间的东西使用;)

ButtonListener bl =new ButtonListener(this);//就是这行代码

 我接着,我们要在DrawListener中同样访问DrawBorder类中通过ButtonListenr传过来的Color属性,同样要传递当前对象给DrawListener,这样才能给画笔设置选中颜色按钮的颜色

                //传递画笔,按钮组管理对象,以及this对象
DrawListener dl =new DrawListener(g,bg,this);

这里真的比较难,传来传去有点绕,只能自己多看书,多积累,多实践了(我觉得还是得把前面堆栈图真正弄明白);

总结:

1、通过对高级画板的功能实现,巩固了监听器的使用,接口实现的方法等知识点;
2、对对象传递有了更深入的理解,以前在看马士兵坦克大战视频中就用到了该知识点,那时候理解不是很透彻,后来在慕课网上自学是也学到了这方面的知识,那时候理解有深入了一些,到现在,应该算是彻底的明白了;
3.坚持,不放弃!总有一天你会学会的!共勉!
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: