我现在还是一个Java的初学者,正在熟悉类库,前几天学习一个例子程序,是一个画图程序,主要的功能是利用鼠标的单击和拖动在一个面板上画出直线,矩形和圆形,一下子看到在事件响应方法中的那么多的代码,脑袋就嗡嗡直响!又想到用户的操作事件可能是随机的,又是先单击后拖动啦,或是先拖动后单击啦,脑子里更是乱的像一锅粥。
但是,还是得硬着头皮看呀,况且成功一定有方法吗,智慧的实质就是找到把复杂的东西变得简单的方法。先说一下我总结出来的方法然后再给大家用这个例子说明一下吧:
大家知道,类的行为是通过方法来体现的,把所有的行为加起来就是这个类的功能,那么当我们要针对某个方法研究它的行为的话,可以按照这个步骤来找出用户的行为给它带来的影响:
1,找出这个方法中用到的外部变量。
2,找出所有的用到这些变量(包括本方法)的并且有可能在本方法发生之前发生的方法。
3,把所有这些方法进行排列,然后再把这些方法的所有子集进行排列(针对某些方法不发生的可能),再把不符合实际情况的排列结果除去,就得到本方法调用前可能面临的所有情况。
4,针对上一步产生的每种情况和各个方法对变量值的改变,得到每种情况产生的变量值的组合。
5,根据每种情况的变量值组合,分析被研究方法的行为。
例子:
先贴上画图例子程序的代码,大家可以复制,编译,运行一下感受一下效果。
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import java.util.*;
class DrawFigure extends JFrame implements MouseListener,MouseMotionListener,AdjustmentListener,ItemListener
{
JPanel p1 = new JPanel();
JPanel p2 = new JPanel();
JPanel top = new JPanel();
JPanel bottom = new JPanel();
ButtonGroup g = new ButtonGroup();
JRadioButton op1 = new JRadioButton("画",true);
JRadioButton op2 = new JRadioButton("直线",false);
JRadioButton op3 = new JRadioButton("圆",false);
JRadioButton op4 = new JRadioButton("矩形",false);
JCheckBox c1 = new JCheckBox("填充");
Color c = Color.black;
JTextArea tt = new JTextArea(2,3);
int f = 1;
int sx,sy,x,y;
boolean fill = false;
boolean flag = false;
JScrollBar r1 = new JScrollBar(JScrollBar.HORIZONTAL,0,4,0,255);
JScrollBar g1 = new JScrollBar(JScrollBar.HORIZONTAL,0,4,0,255);
JScrollBar b1 = new JScrollBar(JScrollBar.HORIZONTAL,0,4,0,255);
public DrawFigure()
{
getContentPane().setLayout(new BorderLayout());
top.setOpaque(true);
top.setBackground(Color.white);
tt.setBackground(Color.black);
p1.setLayout(new FlowLayout());
p1.setBackground(Color.lightGray);
p2.setLayout(new GridLayout(3,1));
p2.setPreferredSize(new Dimension(150,50));
p2.add(r1);p2.add(g1);p2.add(b1);
tt.setEditable(false);
g.add(op1);g.add(op2);g.add(op3);g.add(op4);
p1.add(op1);p1.add(op2);p1.add(op3);p1.add(op4);
p1.add(c1);p1.add(tt);
bottom.add(p1);bottom.add(p2);
c1.addItemListener(this);
r1.addAdjustmentListener(this);
g1.addAdjustmentListener(this);
b1.addAdjustmentListener(this);
op1.addItemListener(this);
op2.addItemListener(this);
op3.addItemListener(this);
op4.addItemListener(this);
top.addMouseListener(this);
top.addMouseMotionListener(this);
getContentPane().add(top,"Center");
getContentPane().add(bottom,"South");
this.setTitle("绘图程序");
setSize(500,300);
setVisible(true);
}
public void mousePressed(MouseEvent e)
{
flag = false;
sx = e.getX();sy = e.getY();
}
public void mouseReleased(MouseEvent e)
{
int x0,y0;
Graphics g = top.getGraphics();
switch(f)
{
case 2:
g.setXORMode(Color.white);
g.drawLine(sx,sy,x,y);
x = e.getX();y = e.getY();
g.setColor(c);
g.setPaintMode();
g.drawLine(sx,sy,x,y);
break;
case 3:
case 4:
g.setXORMode(Color.white);
x0 = x > sx? sx:x;y0 = y > sy? sy:y;
if(!fill)
{
if(f == 3)
g.drawOval(x0,y0,Math.abs(x - sx),Math.abs(y - sy));
else
g.drawRect(x0,y0,Math.abs(x - sx),Math.abs(y - sy));
}
else
{
if(f == 3)
g.fillOval(x0,y0,Math.abs(x - sx),Math.abs(y - sy));
else
g.fillRect(x0,y0,Math.abs(x - sx),Math.abs(y - sy));
}
g.setPaintMode();
x = e.getX();y = e.getY();
x0 = x > sx?sx:x;y0 = y > sy? sy:y;
g.setColor(c);
if(! fill)
{
if(f == 3)
g.drawOval(x0,y0,Math.abs(x - sx),Math.abs(y - sy));
else
g.drawRect(x0,y0,Math.abs(x - sx),Math.abs(y - sy));
}
else
{
System.out.println("出现");
if(f == 3)
g.fillOval(x0,y0,Math.abs(x - sx),Math.abs(y - sy));
else
g.fillRect(x0,y0,Math.abs(x - sx),Math.abs(y - sy));
}
break;
}
}
public void mouseEntered(MouseEvent e){}
public void mouseExited(MouseEvent e){}
public void mouseClicked(MouseEvent e){}
public void mouseMoved(MouseEvent e){}
public void mouseDragged(MouseEvent e){
int x0,y0;
Graphics g = top.getGraphics();
switch(f)
{
case 1:
x = e.getX();y = e.getY();
g.setColor(c);
g.setPaintMode();
g.drawLine(sx,sy,x,y);
sx = x;sy = y;
break;
case 2:
if(! flag)
{
x = e.getX();y = e.getY();
g.setXORMode(Color.white);
g.drawLine(sx,sy,x,y);
flag = true;
}
else
{
g.setXORMode(Color.white);
g.drawLine(sx,sy,x,y);
x = e.getX();y = e.getY();
g.setXORMode(Color.white);
g.drawLine(sx,sy,x,y);
}
break;
case 3:
case 4:
if(! flag)
{
x = e.getX();y = e.getY();
x0 = x > sx ?sx:x;y0 = y>sy?sy:y;
g.setXORMode(Color.white);
if(! fill)
{
if(f == 3)
g.drawOval(x0,y0,Math.abs(x - sx),Math.abs(y - sy));
else
g.drawRect(x0,y0,Math.abs(x - sx),Math.abs(y - sy));
}
else
{
if(f == 3)
g.fillOval(x0,y0,Math.abs(x - sx),Math.abs(y - sy));
else
g.fillRect(x0,y0,Math.abs(x - sx),Math.abs(y - sy));
}
flag = true;
}
else
{
g.setXORMode(Color.white);
x0 = x> sx? sx:x;y0 = y > sy? sy:y;
if(! fill)
{
if(f == 3)
g.drawOval(x0,y0,Math.abs(x - sx),Math.abs(y - sy));
else
g.drawRect(x0,y0,Math.abs(x - sx),Math.abs(y - sy));
}
else
{
if(f == 3)
g.fillOval(x0,y0,Math.abs(x - sx),Math.abs(y - sy));
else
g.fillRect(x0,y0,Math.abs(x - sx),Math.abs(y - sy));
}
x = e.getX();y = e.getY();
x0 = x> sx ? sx:x; y0 = y>sy? sy:y;
if(! fill)
{
if(f == 3)
g.drawOval(x0,y0,Math.abs(x - sx),Math.abs(y - sy));
else
g.drawRect(x0,y0,Math.abs(x - sx),Math.abs(y - sy));
}
else
{
if(f == 3)
g.fillOval(x0,y0,Math.abs(x - sx),Math.abs(y - sy));
else
g.fillRect(x0,y0,Math.abs(x - sx),Math.abs(y - sy));
}
}
break;
}
}
public void actionPerformed(ActionEvent e){
f = Integer.parseInt(e.getActionCommand());
}
public void adjustmentValueChanged(AdjustmentEvent e)
{
c = new Color(r1.getValue(),g1.getValue(),b1.getValue());
tt.setBackground(c);
}
public void itemStateChanged(ItemEvent e)
{
if(e.getItemSelectable() instanceof JCheckBox)
{
JCheckBox temp = (JCheckBox)e.getItemSelectable();
fill = temp.isSelected();
}
else
{
JRadioButton temp = (JRadioButton)e.getItemSelectable();
if(temp == op1)f =1;
else if(temp == op2)f =2;
else if(temp == op3)f = 3;
else if(temp == op4)f = 4;
}
}
public static void main(String[] args)
{
JFrame.setDefaultLookAndFeelDecorated(true);
Font font = new Font("JFrame",Font.PLAIN,14);
Enumeration keys = UIManager.getLookAndFeelDefaults().keys();
while(keys.hasMoreElements())
{
Object key = keys.nextElement();
if(UIManager.get(key) instanceof Font)
UIManager.put(key,font);
}
DrawFigure mainFrame = new DrawFigure();
}
}
好,现在用这个类中的鼠标抬起方法(mouseReleased)举例:
第一步:找出这个方法中用到的外部变量,在这个方法中用到的就是sx,sy,x,y这四个类变量。
第二步:找出所有的用到这些变量(包括本方法)的并且有可能在本方法发生之前发生的方法,在这里就是鼠标按下(mousePressed)鼠标抬起(mouseReleased)和鼠标拖动(mouseDragged)这两个事件处理方法。
第三步:把所有这些方法进行排列,然后再把这些方法的所有子集进行排列(针对某些方法不发生的可能),再把不符合实际情况的排列结果除去,就得到本方法调用前可能面临的所有情况。
先得到16种情况:
1,鼠标按下→鼠标抬起→鼠标拖动;
2,鼠标按下→鼠标拖动→鼠标抬起;
3,鼠标拖动→鼠标按下→鼠标抬起;
4,鼠标拖动→鼠标抬起→鼠标按下;
5,鼠标抬起→鼠标按下→鼠标拖动;
6,鼠标抬起→鼠标拖动→鼠标按下;
7,鼠标抬起→鼠标拖动;
8,鼠标拖动→鼠标抬起;
9,鼠标按下→鼠标抬起;
10,鼠标抬起→鼠标按下;
11,鼠标按下→鼠标拖动;
12,鼠标拖动→鼠标按下;
13,鼠标按下;
14,鼠标拖动;
15,鼠标抬起;
16,任何一个都没发生过。
把不符合实际情况的排列结果除去后,得到5种情况:
1,鼠标拖动→鼠标抬起→鼠标按下;
2,鼠标抬起→鼠标按下→鼠标拖动;
3,鼠标抬起→鼠标按下;
4,鼠标按下→鼠标拖动;
5,鼠标按下;
第四步:针对上一步产生的每种情况和各个方法对变量值的改变,得到每种情况产生的变量值的组合。经过对变量组合的值相同的情况的合并,得到三种情况:
1,鼠标抬起→鼠标按下,这时sx,sy的值等于鼠标按下点的坐标,x,y值等于按下之前鼠标抬起点的坐标。
2,鼠标按下→鼠标拖动,这时sx,sy的值等于鼠标按下点的坐标,x,y值等于鼠标拖动到的点的坐标。
3,鼠标按下,这时sx,sy的值等于鼠标按下点的坐标,x,y值等于原点(0,0)的坐标。
第五步:根据每种情况产生的变量值组合,分析被研究方法的行为。在这个鼠标抬起的事件处理方法中我们就可以得到:
第一种情况下:鼠标抬起→鼠标按下后再抬起的话该方法会根据用户对单选按钮的选择不做处理(任意画图被选中);画一条上一次抬起点到这次单击点的直线(直线被选中);画一个圆(圆被选中)或画一个矩形(矩形被选中)。
第二种情况下:鼠标按下→鼠标拖动后再抬起的话该方法会根据用户对单行按钮的选择沿拖动轨迹画线(任意画图被选中);画一条按下点到拖动后最终抬起点的直线(直线被选中);画一个圆(圆被选中)或画一个矩形(矩形被选中)。
第三种情况下:鼠标第一次按下后抬起的话该方法会根据用户对单选按钮的选择不做处理(任意画图被选中);画一条原点到这次单击点的直线(直线被选中);画一个圆(圆被选中)或画一个矩形(矩形被选中)。
就是这些,水平有限,写得很片面,希望得到大家的批评指正。
但是,还是得硬着头皮看呀,况且成功一定有方法吗,智慧的实质就是找到把复杂的东西变得简单的方法。先说一下我总结出来的方法然后再给大家用这个例子说明一下吧:
大家知道,类的行为是通过方法来体现的,把所有的行为加起来就是这个类的功能,那么当我们要针对某个方法研究它的行为的话,可以按照这个步骤来找出用户的行为给它带来的影响:
1,找出这个方法中用到的外部变量。
2,找出所有的用到这些变量(包括本方法)的并且有可能在本方法发生之前发生的方法。
3,把所有这些方法进行排列,然后再把这些方法的所有子集进行排列(针对某些方法不发生的可能),再把不符合实际情况的排列结果除去,就得到本方法调用前可能面临的所有情况。
4,针对上一步产生的每种情况和各个方法对变量值的改变,得到每种情况产生的变量值的组合。
5,根据每种情况的变量值组合,分析被研究方法的行为。
例子:
先贴上画图例子程序的代码,大家可以复制,编译,运行一下感受一下效果。
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import java.util.*;
class DrawFigure extends JFrame implements MouseListener,MouseMotionListener,AdjustmentListener,ItemListener
{
JPanel p1 = new JPanel();
JPanel p2 = new JPanel();
JPanel top = new JPanel();
JPanel bottom = new JPanel();
ButtonGroup g = new ButtonGroup();
JRadioButton op1 = new JRadioButton("画",true);
JRadioButton op2 = new JRadioButton("直线",false);
JRadioButton op3 = new JRadioButton("圆",false);
JRadioButton op4 = new JRadioButton("矩形",false);
JCheckBox c1 = new JCheckBox("填充");
Color c = Color.black;
JTextArea tt = new JTextArea(2,3);
int f = 1;
int sx,sy,x,y;
boolean fill = false;
boolean flag = false;
JScrollBar r1 = new JScrollBar(JScrollBar.HORIZONTAL,0,4,0,255);
JScrollBar g1 = new JScrollBar(JScrollBar.HORIZONTAL,0,4,0,255);
JScrollBar b1 = new JScrollBar(JScrollBar.HORIZONTAL,0,4,0,255);
public DrawFigure()
{
getContentPane().setLayout(new BorderLayout());
top.setOpaque(true);
top.setBackground(Color.white);
tt.setBackground(Color.black);
p1.setLayout(new FlowLayout());
p1.setBackground(Color.lightGray);
p2.setLayout(new GridLayout(3,1));
p2.setPreferredSize(new Dimension(150,50));
p2.add(r1);p2.add(g1);p2.add(b1);
tt.setEditable(false);
g.add(op1);g.add(op2);g.add(op3);g.add(op4);
p1.add(op1);p1.add(op2);p1.add(op3);p1.add(op4);
p1.add(c1);p1.add(tt);
bottom.add(p1);bottom.add(p2);
c1.addItemListener(this);
r1.addAdjustmentListener(this);
g1.addAdjustmentListener(this);
b1.addAdjustmentListener(this);
op1.addItemListener(this);
op2.addItemListener(this);
op3.addItemListener(this);
op4.addItemListener(this);
top.addMouseListener(this);
top.addMouseMotionListener(this);
getContentPane().add(top,"Center");
getContentPane().add(bottom,"South");
this.setTitle("绘图程序");
setSize(500,300);
setVisible(true);
}
public void mousePressed(MouseEvent e)
{
flag = false;
sx = e.getX();sy = e.getY();
}
public void mouseReleased(MouseEvent e)
{
int x0,y0;
Graphics g = top.getGraphics();
switch(f)
{
case 2:
g.setXORMode(Color.white);
g.drawLine(sx,sy,x,y);
x = e.getX();y = e.getY();
g.setColor(c);
g.setPaintMode();
g.drawLine(sx,sy,x,y);
break;
case 3:
case 4:
g.setXORMode(Color.white);
x0 = x > sx? sx:x;y0 = y > sy? sy:y;
if(!fill)
{
if(f == 3)
g.drawOval(x0,y0,Math.abs(x - sx),Math.abs(y - sy));
else
g.drawRect(x0,y0,Math.abs(x - sx),Math.abs(y - sy));
}
else
{
if(f == 3)
g.fillOval(x0,y0,Math.abs(x - sx),Math.abs(y - sy));
else
g.fillRect(x0,y0,Math.abs(x - sx),Math.abs(y - sy));
}
g.setPaintMode();
x = e.getX();y = e.getY();
x0 = x > sx?sx:x;y0 = y > sy? sy:y;
g.setColor(c);
if(! fill)
{
if(f == 3)
g.drawOval(x0,y0,Math.abs(x - sx),Math.abs(y - sy));
else
g.drawRect(x0,y0,Math.abs(x - sx),Math.abs(y - sy));
}
else
{
System.out.println("出现");
if(f == 3)
g.fillOval(x0,y0,Math.abs(x - sx),Math.abs(y - sy));
else
g.fillRect(x0,y0,Math.abs(x - sx),Math.abs(y - sy));
}
break;
}
}
public void mouseEntered(MouseEvent e){}
public void mouseExited(MouseEvent e){}
public void mouseClicked(MouseEvent e){}
public void mouseMoved(MouseEvent e){}
public void mouseDragged(MouseEvent e){
int x0,y0;
Graphics g = top.getGraphics();
switch(f)
{
case 1:
x = e.getX();y = e.getY();
g.setColor(c);
g.setPaintMode();
g.drawLine(sx,sy,x,y);
sx = x;sy = y;
break;
case 2:
if(! flag)
{
x = e.getX();y = e.getY();
g.setXORMode(Color.white);
g.drawLine(sx,sy,x,y);
flag = true;
}
else
{
g.setXORMode(Color.white);
g.drawLine(sx,sy,x,y);
x = e.getX();y = e.getY();
g.setXORMode(Color.white);
g.drawLine(sx,sy,x,y);
}
break;
case 3:
case 4:
if(! flag)
{
x = e.getX();y = e.getY();
x0 = x > sx ?sx:x;y0 = y>sy?sy:y;
g.setXORMode(Color.white);
if(! fill)
{
if(f == 3)
g.drawOval(x0,y0,Math.abs(x - sx),Math.abs(y - sy));
else
g.drawRect(x0,y0,Math.abs(x - sx),Math.abs(y - sy));
}
else
{
if(f == 3)
g.fillOval(x0,y0,Math.abs(x - sx),Math.abs(y - sy));
else
g.fillRect(x0,y0,Math.abs(x - sx),Math.abs(y - sy));
}
flag = true;
}
else
{
g.setXORMode(Color.white);
x0 = x> sx? sx:x;y0 = y > sy? sy:y;
if(! fill)
{
if(f == 3)
g.drawOval(x0,y0,Math.abs(x - sx),Math.abs(y - sy));
else
g.drawRect(x0,y0,Math.abs(x - sx),Math.abs(y - sy));
}
else
{
if(f == 3)
g.fillOval(x0,y0,Math.abs(x - sx),Math.abs(y - sy));
else
g.fillRect(x0,y0,Math.abs(x - sx),Math.abs(y - sy));
}
x = e.getX();y = e.getY();
x0 = x> sx ? sx:x; y0 = y>sy? sy:y;
if(! fill)
{
if(f == 3)
g.drawOval(x0,y0,Math.abs(x - sx),Math.abs(y - sy));
else
g.drawRect(x0,y0,Math.abs(x - sx),Math.abs(y - sy));
}
else
{
if(f == 3)
g.fillOval(x0,y0,Math.abs(x - sx),Math.abs(y - sy));
else
g.fillRect(x0,y0,Math.abs(x - sx),Math.abs(y - sy));
}
}
break;
}
}
public void actionPerformed(ActionEvent e){
f = Integer.parseInt(e.getActionCommand());
}
public void adjustmentValueChanged(AdjustmentEvent e)
{
c = new Color(r1.getValue(),g1.getValue(),b1.getValue());
tt.setBackground(c);
}
public void itemStateChanged(ItemEvent e)
{
if(e.getItemSelectable() instanceof JCheckBox)
{
JCheckBox temp = (JCheckBox)e.getItemSelectable();
fill = temp.isSelected();
}
else
{
JRadioButton temp = (JRadioButton)e.getItemSelectable();
if(temp == op1)f =1;
else if(temp == op2)f =2;
else if(temp == op3)f = 3;
else if(temp == op4)f = 4;
}
}
public static void main(String[] args)
{
JFrame.setDefaultLookAndFeelDecorated(true);
Font font = new Font("JFrame",Font.PLAIN,14);
Enumeration keys = UIManager.getLookAndFeelDefaults().keys();
while(keys.hasMoreElements())
{
Object key = keys.nextElement();
if(UIManager.get(key) instanceof Font)
UIManager.put(key,font);
}
DrawFigure mainFrame = new DrawFigure();
}
}
好,现在用这个类中的鼠标抬起方法(mouseReleased)举例:
第一步:找出这个方法中用到的外部变量,在这个方法中用到的就是sx,sy,x,y这四个类变量。
第二步:找出所有的用到这些变量(包括本方法)的并且有可能在本方法发生之前发生的方法,在这里就是鼠标按下(mousePressed)鼠标抬起(mouseReleased)和鼠标拖动(mouseDragged)这两个事件处理方法。
第三步:把所有这些方法进行排列,然后再把这些方法的所有子集进行排列(针对某些方法不发生的可能),再把不符合实际情况的排列结果除去,就得到本方法调用前可能面临的所有情况。
先得到16种情况:
1,鼠标按下→鼠标抬起→鼠标拖动;
2,鼠标按下→鼠标拖动→鼠标抬起;
3,鼠标拖动→鼠标按下→鼠标抬起;
4,鼠标拖动→鼠标抬起→鼠标按下;
5,鼠标抬起→鼠标按下→鼠标拖动;
6,鼠标抬起→鼠标拖动→鼠标按下;
7,鼠标抬起→鼠标拖动;
8,鼠标拖动→鼠标抬起;
9,鼠标按下→鼠标抬起;
10,鼠标抬起→鼠标按下;
11,鼠标按下→鼠标拖动;
12,鼠标拖动→鼠标按下;
13,鼠标按下;
14,鼠标拖动;
15,鼠标抬起;
16,任何一个都没发生过。
把不符合实际情况的排列结果除去后,得到5种情况:
1,鼠标拖动→鼠标抬起→鼠标按下;
2,鼠标抬起→鼠标按下→鼠标拖动;
3,鼠标抬起→鼠标按下;
4,鼠标按下→鼠标拖动;
5,鼠标按下;
第四步:针对上一步产生的每种情况和各个方法对变量值的改变,得到每种情况产生的变量值的组合。经过对变量组合的值相同的情况的合并,得到三种情况:
1,鼠标抬起→鼠标按下,这时sx,sy的值等于鼠标按下点的坐标,x,y值等于按下之前鼠标抬起点的坐标。
2,鼠标按下→鼠标拖动,这时sx,sy的值等于鼠标按下点的坐标,x,y值等于鼠标拖动到的点的坐标。
3,鼠标按下,这时sx,sy的值等于鼠标按下点的坐标,x,y值等于原点(0,0)的坐标。
第五步:根据每种情况产生的变量值组合,分析被研究方法的行为。在这个鼠标抬起的事件处理方法中我们就可以得到:
第一种情况下:鼠标抬起→鼠标按下后再抬起的话该方法会根据用户对单选按钮的选择不做处理(任意画图被选中);画一条上一次抬起点到这次单击点的直线(直线被选中);画一个圆(圆被选中)或画一个矩形(矩形被选中)。
第二种情况下:鼠标按下→鼠标拖动后再抬起的话该方法会根据用户对单行按钮的选择沿拖动轨迹画线(任意画图被选中);画一条按下点到拖动后最终抬起点的直线(直线被选中);画一个圆(圆被选中)或画一个矩形(矩形被选中)。
第三种情况下:鼠标第一次按下后抬起的话该方法会根据用户对单选按钮的选择不做处理(任意画图被选中);画一条原点到这次单击点的直线(直线被选中);画一个圆(圆被选中)或画一个矩形(矩形被选中)。
就是这些,水平有限,写得很片面,希望得到大家的批评指正。