Java Notes: GUI Development (Swing)

Java当中有两个GUI库,AWT和Swing。AWT是用非Java代码编写的库,所以对于不同的JVM有unconsistent的效果。但Swing作为一个Java编写的,不存在这个问题。但是Swing当中的事件控制,依然使用的AWT的库。


AWT的引用:java.awt.

Swing: javax.swing.


Java的Swing和Servlet一样,都是使用Cook Book Programming. 


Recipe: 


1/ Create Window Object (JFrame); BTW,通常J开头的都是Swing的类。

2/ Create Container Object (JPanel);

3/ 往这个Container里面加元素(JLabel, JButton, JTextArea, JCheckBox, JChoice, JRadioButton, JTextField, JTextArea, JList, JSrollBar, etc);

4/ 链接container和window (JframeObject.setContentPane(JpanelObject))


控制JPanel的Lay out: 


一般介绍三种Lay out: FlowLayout (default), BorderLayout and GridLayout. 


FlowLayout:将你加入到container的元素从左到右地排列,如果当前行满了不够放,则新开一行。


Border Layout: 把元素加入上、下、左、右和中,5个区域。


Grid Layout: 为每个元素定大小,变为等大小的网格。一开始就要指定行数和列数。


如何人为控制Lay out: 


自己新建一个panel,然后手工加入到最早的panel当中


JPanel pane = new JPanel();
JPanel line = new JPanel();

JButton button = new JButton(new ImageIcon("obama.jpg"));
line.add(button);

JButton button2 = new JButton(new ImageIcon("trump.jpg"));
line.add(button2);

pane.add(line);


Swing当中的字体控制(用awt):


java.awt.Font bigFont = new Font(Font.SERIF, Font.BOLD, 20);

JLabelObject,setFont(bigFont);


Swing的Action监听:


Action的监听是UI设计的核心。如何一个UI无法通过Action监听获取用户的行为,那么这个UI将毫无意义。Swing 的Event listener(实际是AWT的)有以下:


ActionListener, AdjustmentListener, FocusListener, ItemListener, KeyListener, MouseListener... 


ActionListener主要监听JButtons and JTextFields等等我们常用的元素。使用这个Listener需要建立一个ActionListener的实现类。实现其中的actionPerformed()的抽象方法。一般会在这个方法的实现当中调用event.getSource()或者event.getActionCommand()来确定是来自哪个component的动作。


实现例子:


 * Method to be invoked when buttons are clicked.
     * @param event event object
     */
    @Override
    public void actionPerformed(ActionEvent event) {
        if (event.getSource() == obamaButton) {
            textArea.append("Yes we can!\n");
            return;
        }

        if (event.getSource() == trumpButton) {
            textArea.append("You're fired!\n");
            return;
        }
        
        throw new AssertionError("Unknown event.");
    }

最后,别忘了把这个ActionListener和对应的component绑定。(e.g.: obamaButton.addActionListener(this);)


Swing的组织(组合上述的代码):


两个建议:1) actionPerformed里面的代码不要写太长,写一些helper函数,显得代码容易读懂;2)对于要在actionPerformed里面调用的component,把它们声明为对象成员,便于调用,其余可以继续作为方法里面的临时变量。在Eclipse里面,Brown是临时变量,而Blue是对象成员。


组织Key One: 把Recipe放到哪里?


首先,很自然的想到的是都放进main函数里。然而,放在main函数有一个很大的drawback,便是作为一个static函数,无法调用非static的成员。在实现ActionListener的时候很有困难,十分不建议。


那么还存在另外的两种:1)创建一个类,类的构造器完成上述recipe的内容;2)创建一个JFrame的子类,然后除了JFrame,构造器完成剩下的recipe的内容。个人比较Prefer前一种。所以,在这里讲第一种。


组织Key Two: 如何实现ActionListener? 


1)直接把上述创建的类implements ActionListener,然后在类里面实现actionPerformed方法即可。但是这样有个不好的地方,整个类当中,只能有一个ActionListener了。在某些应用场景,这是不够的;


2) 在上述创建的类当中创建一个内部类(nested class),内部类分为static的或者非static的。如果用static的内部类,无法调用对象成员,只能把对象成员作为构造器方法的参数传进去方法进行处理:


static的处理方法:


private static class ObamaActionListener implements ActionListener {
        private JTextArea area;

        public ObamaActionListener(JTextArea a) {
            area = a;
        }

        public void actionPerformed(ActionEvent event) {
            area.append("Yes we can!\n");
        }
    }


有同学可能会问,为什么不能把Component变为类的static成员呢?因为这与我们的设计初衷相悖了。我们这里需要每个类的对象代表一个新的窗口。如果我们类的对象(窗口)都共享相同Component的话,会有什么后果?敲黑板,这很重要哦。


非static版本的处理方法:


如果是非static的内部类的话,很明显不存在无法调用对象成员的问题。但是,需要注意的是,调用这个内部类需要先初始化一个对象。否则,是无法用到这个内部类的方法的。


所以应该使用这样的style: 


public class QuoteGUIAction1b {
......

    public QuoteGUIAction1b() {
        .......
        // Instantiate an ActionLister
        ActionListener listener = new MyActionListener();
        obamaButton.addActionListener(listener);
        ......
    }
    private class MyActionListener implements ActionListener {
        public void actionPerformed(ActionEvent event) {
            if (event.getSource() == obamaButton) {
                textArea.append("Yes we can!\n");
                return;
            }

            if (event.getSource() == trumpButton) {
                textArea.append("You're fired!\n");
                return;
            }

            throw new AssertionError("Unknown event.");
        }
    }
}

3) 当然,如果觉得每个Listener都要创建一个内部类太麻烦,可以创建匿名类:


// anonymous class that implements ActionListener
        obamaButton.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                textArea.append("Yes we can!\n");
            }
        });

// anonymous class that implements ActionListener
        trumpButton.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                textArea.append("You're fired!\n");
            }
        });









  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值