前面的几篇笔记都写得太古板了,今天就换个新的写作风格来试试,暂且叫“案例导向式”吧,希望能对自己和别人的学习有所帮助。

 

第一部分 问题场景描述


     
某日,小菜跑来问我:“phinecos,我真是快被java逼疯了,你可得帮帮我呀!!“

                我转过头,“怎么了,小菜?“。

                “是这样的,我现在在学习swing,每次用一个控件吧,如果想知道它能处理的事件的话,就得去查jdk文档,可sun那该死的文档总是把人搞得头晕,我只不过是想看看有什么事件可以处理而已,它那乱七八糟的文档反而把我快逼疯了,你给我出出主意吧。。。“小菜着急地摇着我的手说。

                 “哦,原来是这样啊,恩,可为什么你不用eclipse哪?它有提供你所需要的功能啊。”我不解的问。

                 “。。。这个,我不是不想用啊,可听人说,高手都是只用记事本和jdk的,我想成为高手,所以不敢用呀。”小菜支支唔晤的说。

                     “。。。。。。”

 

第二部分 分析与设计

       需求是软件的关键。碰到上面小菜的问题了,我们就开始进行分析吧。小菜到底有什么需求哪?他是想查看一个swing控件类能够处理的事件列表,也就是它的所有addXXXListener方法。怎么办哪?看来只有两个解决方案了:一,劝小菜用eclipse,这样就可以直接利用eclipse的功能满足他的需求。(可这个已经被否定了,因为小菜要成为“高手”,^o^.二,那就只有为他开发一个小实用工具,让他可以查看各个Swing控件能够处理的事件,也就是把它的所有addXXXListener方法都列出来。

       好了,东西比较小,那就先从GUI界面开始,至于核心的事件处理先不管,如下图:

6-6-1.GIF


用户界面代码如下:


None.gifpackage com.vitamin.UI;
None.gif
None.gifimport java.awt.ActiveEvent;
None.gifimport java.awt.BorderLayout;
None.gifimport java.awt.Container;
None.gifimport java.awt.Event;
None.gifimport java.awt.
event.ActionEvent;
None.gifimport java.awt.
event.ActionListener;
None.gif
None.gifimport javax.swing.
*;
None.gif
None.gifimport com.vitamin.Console.console;
None.gif
None.gif
None.gif
public class ShowAddListeners extends JFrame
ExpandedBlockStart.gifContractedBlock.gif
dot.gif{
InBlock.gif    
private JLabel lbName = null;
InBlock.gif    
private JTextField tfName = null;
InBlock.gif    
private JTextArea tResult = null;
InBlock.gif    
private JPanel pName = null;
InBlock.gif    
InBlock.gif    
public ShowAddListeners() 
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
InBlock.gif        super();
InBlock.gif        
this.initForm();
ExpandedSubBlockEnd.gif    }

InBlock.gif    
public ShowAddListeners(String title)
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
InBlock.gif        super(title);
InBlock.gif        
this.initForm();
ExpandedSubBlockEnd.gif    }

InBlock.gif    
private void initForm()
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
InBlock.gif        
this.lbName = new JLabel("请输入Swing控件的类名:");
InBlock.gif        
this.tfName = new JTextField(20);
InBlock.gif        
this.tResult = new JTextArea(40,50);
InBlock.gif        
InBlock.gif        
this.pName = new JPanel();
InBlock.gif        pName.add(
this.lbName);
InBlock.gif        pName.add(
this.tfName);
InBlock.gif        
InBlock.gif        Container con 
= this.getContentPane();
InBlock.gif        con.add(BorderLayout.NORTH,pName);
InBlock.gif        con.add(
new JScrollPane(this.tResult));
InBlock.gif        
InBlock.gif        tfListener tf1 
= new tfListener();
InBlock.gif        
this.tfName.addActionListener(tf1);
InBlock.gif        
console.run(this,600,600);
ExpandedSubBlockEnd.gif    }

InBlock.gif    
class tfListener implements ActionListener
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
InBlock.gif        
public void actionPerformed(ActionEvent e)
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{//核心处理代码处
InBlock.gif            
if(tfName.getText().length()==0)
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif                JOptionPane.showMessageDialog((JTextField)e.getSource(),
"请输入控件类名称!!!","错误信息",JOptionPane.DEFAULT_OPTION);
InBlock.gif                
return;
ExpandedSubBlockEnd.gif            }

InBlock.gif            JOptionPane.showMessageDialog((JTextField)e.getSource(),
"OK","信息",JOptionPane.DEFAULT_OPTION);
ExpandedSubBlockEnd.gif        }

ExpandedSubBlockEnd.gif    }

ExpandedSubBlockStart.gifContractedSubBlock.gif    
/**//**
InBlock.gif     * @param args
ExpandedSubBlockEnd.gif     
*/

InBlock.gif    
public static void main(String[] args)
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
InBlock.gif        ShowAddListeners sl 
= new ShowAddListeners("事件查看器");
ExpandedSubBlockEnd.gif    }

InBlock.gif
ExpandedBlockEnd.gif}

None.gif

    在这里我对用户引发的键盘事件还只是简单地进行一个测试用的显示处理,还没有添加进用来完成所需功能的代码,但提早让用户体验到模型,哪怕是一个没有具体功能的虚模型也是一件好事情。

       恩,问题来了,接收到用户输入的swing控件类名以后,该怎么去读取它所有的方法,并且能把adeeXXXListener()这样类型的方法给显示在TextArea控件里给用户哪?我第一反应是:要想获取一个类的所有方法,应该用RTTI,先用类名构造一个Class,再去尝试获取其方法。至于想从读出来的所有方法中只选出adeeXXXListener()类型的方法,应该要使用正则表达式来进行模式匹配吧。现有的思路是这样的,可对RTTI, 正则表达式,我都不熟悉,该怎么办哪?看来得靠jdk文档和google了。

好吧,打开jdk文档开始看Class的知识吧:

        public static Class<?> forName(String className)

                        throws ClassNotFoundException

返回与带有给定字符串名的类或接口相关联的 Class 对象。调用此方法等效于:

  Class.forName(className, true, currentLoader)

 

其中 currentLoader 表示此类的定义类加载器。

例如,以下代码片段返回 java.lang.Thread 类的运行时 Class 描述符。

   Class t = Class.forName("java.lang.Thread")

 

调用 forName("X") 将导致名为 X 的类被初始化。

恩,正是我要的,仿上面给的例子,我应该这样做:先获取用户输入的swing控件名称,如JButton,然后:]

        Class t=  Class.forName("java.swing."+name);

 

   现在有了运行时的类了,接下来就是获取它的所有方法了
   
那我就应该这样:Method[] mt = t. getMethod();这样就把所有的方法读取到数组mt中了。
修改后的效果:
   6-6-3.GIF

修改后的事件处理代码:
   

None.gifclass tfListener implements ActionListener
ExpandedBlockStart.gifContractedBlock.gif    
dot.gif{
InBlock.gif        
public void actionPerformed(ActionEvent e)
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            String name 
= tfName.getText().trim();
InBlock.gif            Class clName 
= null;
InBlock.gif            
if(name.length()==0)
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif                JOptionPane.showMessageDialog((JTextField)e.getSource(),
"请输入控件类名称!!!","错误信息",JOptionPane.DEFAULT_OPTION);
InBlock.gif                
return;
ExpandedSubBlockEnd.gif            }

InBlock.gif            
else
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif                
try
ExpandedSubBlockStart.gifContractedSubBlock.gif                
dot.gif{
InBlock.gif                    clName 
= Class.forName("javax.swing."+name);
InBlock.gif                    Method[] mt 
= clName.getMethods();
InBlock.gif                    
for(int i=0;i<mt.length;i++)
ExpandedSubBlockStart.gifContractedSubBlock.gif                    
dot.gif{
InBlock.gif                        tResult.append(mt[i].toString()
+"\n");
ExpandedSubBlockEnd.gif                    }

ExpandedSubBlockEnd.gif                }

InBlock.gif                
catch(ClassNotFoundException ex)
ExpandedSubBlockStart.gifContractedSubBlock.gif                
dot.gif{
InBlock.gif                    tResult.setText(
"没有找到匹配的方法名!!!");
ExpandedSubBlockEnd.gif                }

ExpandedSubBlockEnd.gif            }

ExpandedSubBlockEnd.gif        }

ExpandedBlockEnd.gif    }

   现在已经初具雏形了,可获取的是全部方法,并不是我们原本想要的东西,还得从这个方法列表中进行一些筛选工作才行。
   要选出只含有addXXXListener的方法,就应该尝试构造一个能够识别这样方法的正则表达式。翻阅jdk文档后,我写了这样一个正则表达式:

private static String StrReg = "add\\w+?Listener";其中\\w+?表示一个或多个字符

   为了学习如何编写识别一个简单模式的程序,我写了一个简单的测试程序:

None.gifpackage com.vitamin.Console;
None.gifimport java.util.regex.
*;
None.gif
None.gif
public class regTest 
ExpandedBlockStart.gifContractedBlock.gif
dot.gif{
InBlock.gif
InBlock.gif    
public static void main(String[] args)
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
InBlock.gif        Pattern p 
= null;
InBlock.gif        Matcher m 
= null;
InBlock.gif        p 
= Pattern.compile("a*b");
InBlock.gif        m 
= p.matcher("aaaaab");
InBlock.gif        
if(m.matches()==true)
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            System.
out.println("模式匹配成功");
ExpandedSubBlockEnd.gif        }

InBlock.gif        
else
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            System.
out.println("匹配失败");
ExpandedSubBlockEnd.gif        }

InBlock.gif
ExpandedSubBlockEnd.gif    }

InBlock.gif
ExpandedBlockEnd.gif}

None.gif

 

   现在就来完成剩余的工作,代码如下:

None.gifpackage com.vitamin.UI;
None.gif
None.gifimport java.awt.ActiveEvent;
None.gifimport java.awt.BorderLayout;
None.gifimport java.awt.Container;
None.gifimport java.awt.Event;
None.gifimport java.awt.
event.ActionEvent;
None.gifimport java.awt.
event.ActionListener;
None.gifimport java.lang.reflect.Method;
None.gifimport java.util.regex.
*;
None.gifimport javax.swing.
*;
None.gif
None.gifimport com.vitamin.Console.console;
None.gif
None.gif
None.gif
public class ShowAddListeners extends JFrame
ExpandedBlockStart.gifContractedBlock.gif
dot.gif{
InBlock.gif    
private JLabel lbName = null;
InBlock.gif    
private JTextField tfName = null;
InBlock.gif    
private JTextArea tResult = null;
InBlock.gif    
private JPanel pName = null;
InBlock.gif    
private static String StrReg = "add\\w+?Listener";
InBlock.gif    
private static  Pattern pt = Pattern.compile(StrReg);
InBlock.gif    
private static Matcher mc = null;
InBlock.gif    
public ShowAddListeners() 
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
InBlock.gif        super();
InBlock.gif        
this.initForm();
ExpandedSubBlockEnd.gif    }

InBlock.gif    
public ShowAddListeners(String title)
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
InBlock.gif        super(title);
InBlock.gif        
this.initForm();
ExpandedSubBlockEnd.gif    }

InBlock.gif    
private void initForm()
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
InBlock.gif        
this.lbName = new JLabel("请输入Swing控件的类名:");
InBlock.gif        
this.tfName = new JTextField(20);
InBlock.gif        
this.tResult = new JTextArea(40,50);
InBlock.gif        
InBlock.gif        
this.pName = new JPanel();
InBlock.gif        pName.add(
this.lbName);
InBlock.gif        pName.add(
this.tfName);
InBlock.gif        
InBlock.gif        Container con 
= this.getContentPane();
InBlock.gif        con.add(BorderLayout.NORTH,pName);
InBlock.gif        con.add(
new JScrollPane(this.tResult));
InBlock.gif        
InBlock.gif        tfListener tf1 
= new tfListener();
InBlock.gif        
this.tfName.addActionListener(tf1);
InBlock.gif        
InBlock.gif        console.run(
this,600,600);
ExpandedSubBlockEnd.gif    }

InBlock.gif    
class tfListener implements ActionListener
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
InBlock.gif        
public void actionPerformed(ActionEvent e)
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            String name 
= tfName.getText().trim();
InBlock.gif            Class clName 
= null;
InBlock.gif            
if(name.length()==0)
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif                JOptionPane.showMessageDialog((JTextField)e.getSource(),
"请输入控件类名称!!!","错误信息",JOptionPane.DEFAULT_OPTION);
InBlock.gif                
return;
ExpandedSubBlockEnd.gif            }

InBlock.gif            
else
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif                
try
ExpandedSubBlockStart.gifContractedSubBlock.gif                
dot.gif{
InBlock.gif                    clName 
= Class.forName("javax.swing."+name);
InBlock.gif                    Method[] mt 
= clName.getMethods();
InBlock.gif                    
for(int i=0;i<mt.length;i++)
ExpandedSubBlockStart.gifContractedSubBlock.gif                    
dot.gif{
InBlock.gif                        mc 
= pt.matcher(mt[i].toString());
InBlock.gif                        
if(mc.find())
ExpandedSubBlockStart.gifContractedSubBlock.gif                        
dot.gif{
InBlock.gif                            tResult.append(mt[i].toString()
+"\n");
ExpandedSubBlockEnd.gif                        }

ExpandedSubBlockEnd.gif                    }

ExpandedSubBlockEnd.gif                }

InBlock.gif                
catch(ClassNotFoundException ex)
ExpandedSubBlockStart.gifContractedSubBlock.gif                
dot.gif{
InBlock.gif                    tResult.setText(
"没有找到匹配的方法名!!!");
ExpandedSubBlockEnd.gif                }

ExpandedSubBlockEnd.gif            }

ExpandedSubBlockEnd.gif        }

ExpandedSubBlockEnd.gif    }

ExpandedSubBlockStart.gifContractedSubBlock.gif    
/**//**
InBlock.gif     * @param args
ExpandedSubBlockEnd.gif     
*/

InBlock.gif    
public static void main(String[] args)
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
InBlock.gif        ShowAddListeners sl 
= new ShowAddListeners("事件查看器");
ExpandedSubBlockEnd.gif    }

InBlock.gif
ExpandedBlockEnd.gif}

None.gif


结果如下,虽然还有很多地方不成熟,但也算是我的一个小作品吧,^o^


6-6-5.GIF