利用继承高效率写程序

2005年2月3日3:41:41

问题:
如果有两个JPopupMenu:a,b
a有个JMenu, b也有,但是b比a要多一个JMenuItem

我们用大写字母代表按钮上的名字
                  

                               __D
按钮a:   A__C__|__E
                              |__F

 

                           __D
                   C__|__E
                    |      |__F
按钮b    B--|  
                    |--G

         
我最初这样写的:

JPopupMenu a = new JPopupMenu("A");
JPopupMenu b = new JPopupMenu("B");
JMenu c = new JPopupMenu();        //想让a和b公有c     *_*
JMenuItem d = new JMenuItem("D");
JMenuItem e = new JMenuItem("E");
JMenuItem f = new JMenuItem("F");
c.add(d);
c.add(e);
c.add(f);
a.add(c);
现在的实际情况:a按钮是这样的
                __D
A__C__|__E
               |__F
好的,继续。
b.add(c);    //这条语句是后面失败的原因
JMenuItem g = new JMenuItem("G");
b.add(g);
到现在我想象的情况是:
                __D
A__C__|__E
               |__F

              __D
      C__|__E
       |      |__F
 B--|   
      |--G

但是一个组件是不能同时在两个Compoment里面的,所以
在b.add(c);这一句后,本来在a里面的c跑到b上面去了。
所以现在的实际情况是:

-


              __D
      C__|__E
      |      |__F
 B--|  
      |--G
正如我们所见,按钮a什么都没了:(

那么怎么办呢??
在我脑海里首先得到的解决方法是安步就班的一个一个写,
a和b重复的部分就要写两遍。
举个例子,这样写:(当然我没有这样写,为重复的每个按钮变量生成啊,取名啊,设置字体啊,设置颜色啊。。。太累了)

JPopupMenu a = new JPopupMenu("A");
JPopupMenu b = new JPopupMenu("B");
JMenu c = new JPopupMenu();
JMenuItem d = new JMenuItem("D");
JMenuItem e = new JMenuItem("E");
JMenuItem f = new JMenuItem("F");
c.add(d);
c.add(e);
c.add(f);
a.add(c);//a结束
JMenu g = new JPopupMenu();
JMenuItem h = new JMenuItem("D");
JMenuItem i = new JMenuItem("E");
JMenuItem j = new JMenuItem("F");
g.add(h);
g.add(i);
g.add(j);
JMenuItem k = new JMenuItem("G");
b.add(g);
b.add(k);//b结束
好了,现在的实际结果一定是正确的。
看上去假设这么写的好象没多少代码量,但是如前面所说,我们这只是做演示,加上字体、颜色、监听器等等实际上的代码量是非常大的!
其实最大的问题还不是代码量的问题,问题是你的程序的可读性大大降低了!!
要知道swing程序员不仅要构建复杂而且友好的界面,还要对大量的各种事件写监听器,在一大堆难读的代码中寻找按钮还不如要人家去电影院看100遍《2046》:)(2046实在难看,我直说好了)
我们需要让我们的程序可读性高,我不记得是哪位高手说的了:在一份程序的生命周期里,10%的时间用来写它,90%的时间是拿来给人家看的。
诸多原因,我们务必用优雅的方式解决问题:)

我最开始是这样想的:
能否自己写一个MyPopupMenu extends JPopupMenu
如果MyPopupMenu p = new MyPopupMenu();
有一部分MenuItem是已经存在在p里了?

经过实践,实践是真理:)
很快就搞定了。方法是这样的:
制作我们自己的MyJPopupMenu类,它继承自JPopupMenu,把公有的部分全部写进去,这样无论要怎么增加JMenuItem都不会烦了.
MyJPopupButton类如下:
假设在主类ManagerUI.java里面
public class ManagerUI
{
    private ...
    private Font font = new Font(...);
    private Color buttonColor = new Color(...);
    ...
    public ManagerUI()
    {
    ......
    }
    //这里是JPopupMenu的监听器
    private class MyPopupMenuListener implements ActionListener
    {
        ......
    }
    private class MyJPopupMenu extends JPopupMenu
    {
        private JMenuItem d = new JMenuItem("D");
        private JMenuItem e = new JMenuItem("E");
        private JMenuItem f = new JMenuItem("F");
        public MyJPopupMenu()
        {
        }
        public MyJPopupMenu(String name)
        {
            super(name);
        }
        //全部在这个方法里面一次性搞顶了,每个组件等会只需调用一下这个
        //public方法就ok了
        public void addPublicMenuItem()
        {
            //设置字体
            d.setFont(font);
            //设置颜色            
            d.setBackgroundColor(buttonColor); 
            e.setFont(font);
            e.setBackgroundColor(buttonColor);
            f.setFont(font);
            f.setBackgroundColor(buttonColor); 
            MyPopopMenuListener mp = new MyPopopMenuListener();
            d.addActionListener(mp); 
            e.addActionListener(mp);
            f.addActionListener(mp);        
            c.add(d);
            c.add(e);
            c.add(f);
            add(c);     //注意add()方法是继承超类JPopupMenu的
        }
    }
}

在原来需要产生JPopupMenu的地方加上我们的对象,代码是这样的:
public class ManagerUI
{
    private ...
    private Font font = new Font(...);
    private Color buttonColor = new Color(...);
    private JPopupMenu a;//注意这里我们是用公共类,MyJPopupMenu的
    private JPopupMenu b;//父类做的声明,等会需要向下转型
    ...
    public ManagerUI()
    {
        ......
   
        a = new MyJPopupMenu("A");               //非常简洁
        (MyJPopupMenu)a.addPublicMenuItem();     //记得向下转型
        b = new MyJPopupMenu("B");            
        (MyJPopupMenu)b.addPublicMenuItem();  
        JMenuItem c = new JMenuItem("G");      
        b.add(c);  
       
        .....                      
   
    }
    //这里是JPopupMenu的监听器
    private class MyPopupMenuListener implements ActionListener
    {
        public void actionPerformed(ActionEvent event)
        {
            String id = ((JMenuItem)event.getSource()).getActionCommand();
            if(id.equals("D"))
            {...}
            else if(id.equals("E"))
            {...}
            else if(id.equals("F"))
            {...}
            else if(id.equals("G"))
            {...}
        }
    }
    private class MyJPopupMenu
    extends JPopupMenu
    implement ActionListener
    {
        private JMenuItem d = new JMenuItem("D");
        private JMenuItem e = new JMenuItem("E");
        private JMenuItem f = new JMenuItem("F");
        public MyJPopupMenu()
        {
        }
        public MyJPopupMenu(String name)
        {
            super(name);
        }
        public void addPublicMenu()
        {
            d.setFont(font);
            d.setBackgroundColor(buttonColor);
            e.setFont(font);
            e.setBackgroundColor(buttonColor);
            f.setFont(font);
            f.setBackgroundColor(buttonColor); 
            MyPopopMenuListener mp = new MyPopopMenuListener();
            d.addActionListener(mp); 
            e.addActionListener(mp);
            f.addActionListener(mp);        
            c.add(d);
            c.add(e);
            c.add(f);
            add(c);
        }
    }
}

最后运行的情况不用我说了,绝对正确无误:)
完了吗?
记得James Cooper说过反正他认为类越多就越难管理,我们可以进一步进行优化,
把JPopupMenu按钮的监听器类删掉吧,为什么不呢?
很简单,只需要用MyJPopupMenu类实现ActionListener接口就可以了
这样完整代码变成这样:

public class ManagerUI
{
    private ...
    private Font font = new Font(...);
    private Color buttonColor = new Color(...);
    private JPopupMenu a;
    private JPopupMenu b;
    ...
    public ManagerUI()
    {
        ......
   
        a = new MyJPopupMenu("A");              
        (MyJPopupMenu)a.addPublicMenuItem();    
        b = new MyJPopupMenu("B");            
        (MyJPopupMenu)b.addPublicMenuItem();  
        JMenuItem c = new JMenuItem("G");      
        b.add(c);  
       
        .....                      
   
    }
    private class MyJPopupMenu
    extends JPopupMenu
    implement ActionListener
    {
        private JMenuItem d = new JMenuItem("D");
        private JMenuItem e = new JMenuItem("E");
        private JMenuItem f = new JMenuItem("F");
        public MyJPopupMenu()
        {
        }
        public MyJPopupMenu(String name)
        {
            super(name);
        }
        public void addPublicMenu()
        {
            d.setFont(font);
            d.setBackgroundColor(buttonColor);
            e.setFont(font);
            e.setBackgroundColor(buttonColor);
            f.setFont(font);
            f.setBackgroundColor(buttonColor); 
            MyPopopMenuListener mp = new MyPopopMenuListener();
            d.addActionListener(this); //注意:记得把这里改成this
            e.addActionListener(this);
            f.addActionListener(this);        
            c.add(d);
            c.add(e);
            c.add(f);
            add(c);
        }
        //把actionPerformed()方法写到这里
        public void actionPerformed(ActionEvent event)
        {
            String id = ((JMenuItem)event.getSource()).getActionCommand();
            if(id.equals("D"))
            {...}
            else if(id.equals("E"))
            {...}
            else if(id.equals("F"))
            {...}
            else if(id.equals("G"))
            {...}
        }
    }
}
终于搞定了,以上代码为了方便阅读用a,b,c...等字母表示的,实际情况当然不是这样:)
小结:
没有什么技术含量...:)
我是菜鸟,平时注意自我总结小经验对自己的Java水平一定有帮助的:)

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值