事件處理可以簡單地這麼理解,當有一個事件產生,程式要根據這個事件做出回應。例如,我們做了一個可以透過按鈕改變背景顏色的窗口,當我們點擊按鈕時便產生了一個事件,程式會根據這個事件來做出回應,也就是去改變背景的顏色。
那麼程式是怎麼做出回應的呢?這就需要事件監聽器ActionListener,這是一個接口,裡麵包含了actionPerformed方法(也就是根據事件去執行的操作),所以我們要實現這個接口(實現接口裡的actionPerformed方法)做出一個監聽器對像出來,並且用按鈕來註冊這個監聽器對象,這樣當按鈕被點擊的時候,就會調用這個監聽器來執行響應了。
運作結果
碼如果將ColorAction類別獨立出去,需要將buttonPanel傳遞到ColorAction,實作如下:
package buttonPanel; import java.awt.*; import java.awt.event.*; //事件监听器接口ActionListener的位置。 import javax.swing.*; public class ButtonFrame extends JFrame { private ButtonPanel buttonPanel; private static final int DEFAULT_WIDTH = 300; private static final int DEFAULT_HEIGHT = 200; public ButtonFrame() { setSize(DEFAULT_WIDTH,DEFAULT_HEIGHT); setLocationByPlatform(true); //构造按钮 JButton redButton = new JButton("RED"); JButton yellowButton = new JButton("YELLOW"); JButton blueButton = new JButton("BLUE"); buttonPanel = new ButtonPanel(); //添加按钮到面板 buttonPanel.add(redButton); buttonPanel.add(yellowButton); buttonPanel.add(blueButton); add(buttonPanel); //构造对应颜色的动作监听器 ColorAction redAction = new ColorAction(Color.red); ColorAction yellowAction = new ColorAction(Color.yellow); ColorAction blueAction = new ColorAction(Color.blue); //每个按钮注册对应的监听器 redButton.addActionListener(redAction); yellowButton.addActionListener(yellowAction); blueButton.addActionListener(blueAction); } //为了方便调用buttonPanel,将ColorAction作为ButtonFrame的内部类。 private class ColorAction implements ActionListener { private Color backgroundColor; public ColorAction(Color c) { backgroundColor = c; } public void actionPerformed(ActionEvent event) { buttonPanel.setBackground(backgroundColor); } } public static void main(String[] args) { EventQueue.invokeLater(new Runnable() { public void run() { JFrame frame = new ButtonFrame(); frame.setTitle("ColorButton"); frame.setDefaultCloseOperation(EXIT_ON_CLOSE); frame.setVisible(true); } }); } } class ButtonPanel extends JPanel { private static final int DEFAUT_WIDTH = 300; private static final int DEFAUT_HEIGHT = 200; @Override protected void paintComponent(Graphics g) { g.create(); super.paintComponent(g); } @Override public Dimension getPreferredSize() { return new Dimension(DEFAUT_WIDTH,DEFAUT_HEIGHT); } }
程式碼有一個缺陷,就是在建構按鈕、新增按鈕到面板、建構對應顏色的監聽器和註冊監聽器的時候有程式碼複製的情況,為了避免程式碼複製,我們可以建立一個makeButton方法,把這些重複的操作包含在內,實作如下:
package buttonPanel2; import java.awt.*; import java.awt.event.*; import javax.swing.*; public class ButtonFrame2 extends JFrame { private ButtonPanel buttonPanel; private static final int DEFAULT_WIDTH = 300; private static final int DEFAULT_HEIGHT = 200; public ButtonFrame2() { setSize(DEFAULT_WIDTH,DEFAULT_HEIGHT); setLocationByPlatform(true); JButton redButton = new JButton("RED"); JButton yellowButton = new JButton("YELLOW"); JButton blueButton = new JButton("BLUE"); buttonPanel = new ButtonPanel(); buttonPanel.add(redButton); buttonPanel.add(yellowButton); buttonPanel.add(blueButton); add(buttonPanel); //将此对象通过this传到ColorAction的构造器。 ColorAction redAction = new ColorAction(this,Color.red); ColorAction yellowAction = new ColorAction(this,Color.yellow); ColorAction blueAction = new ColorAction(this,Color.blue); redButton.addActionListener(redAction); yellowButton.addActionListener(yellowAction); blueButton.addActionListener(blueAction); } public void setButtonPanelsBackground(Color backgroundColor) { buttonPanel.setBackground(backgroundColor); } public static void main(String[] args) { EventQueue.invokeLater(new Runnable() { public void run() { JFrame frame = new ButtonFrame2(); frame.setTitle("ColorButton"); frame.setDefaultCloseOperation(EXIT_ON_CLOSE); frame.setVisible(true); } }); } } class ColorAction implements ActionListener { private ButtonFrame2 buttonFrame; private Color backgroundColor; //通过构造器的方法把ButtonFrame2对象传过来,这个对象包含了成员变量buttonPanel,以便对其更换背景色。 public ColorAction(ButtonFrame2 buttonFrame,Color c) { this.buttonFrame = buttonFrame; //this.buttonFrame只是对象管理者,管理的还是ButtonFrame的对象frame。 backgroundColor = c; } public void actionPerformed(ActionEvent event) { buttonFrame.setButtonPanelsBackground(backgroundColor); //这是我们在ButtonFrame2中添加的新方法。 } } class ButtonPanel extends JPanel { private static final int DEFAUT_WIDTH = 300; private static final int DEFAUT_HEIGHT = 200; public ButtonPanel() { setBackground(Color.pink); } @Override protected void paintComponent(Graphics g) { g.create(); super.paintComponent(g); } @Override public Dimension getPreferredSize() { return new Dimension(DEFAUT_WIDTH,DEFAUT_HEIGHT); } } ButtonFrame2
在程式碼中,監聽器只被呼叫了一次,也就是在addActionListener()時。所以我們沒有必要為監聽器單獨做一個類別出來,而是只需在用到監聽器時直接new一個ActionListener接口出來,並在花括號裡實現接口方法即可。