2007/03/08

在 Java 中讓不同的按鍵有不同的動作

通常一個視窗中會有多個不同的按鈕,點下按鈕後,按鈕會分別有不同的動作。

假設我們寫了一個 JTextArea 讓使用者輸入資料,當按下「Add Line」按鈕時會自動換行,按下「Exit」按鈕時會結束程式。




程式碼:

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;

public class panel0 {

JFrame frame = new JFrame();
JPanel panel = new JPanel();
JButton b1 = new JButton("Exit");
JButton b2 = new JButton("Add Line");
JTextArea text = new JTextArea(5,10);
JPanel panelControl = new JPanel();



public static void main(String[] arg){
panel0 gui = new panel0();
gui.go();
}

public void go(){

panel.setBackground(Color.gray);
panel.setLayout(new BoxLayout(panel,BoxLayout.Y_AXIS));

panelControl.setBackground(Color.gray);
panelControl.setLayout(new BoxLayout(panelControl,BoxLayout.X_AXIS) );

text.setLineWrap(true);
JScrollPane scroller = new JScrollPane(text);
scroller.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS);
scroller.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);

b1.addActionListener(this);
b2.addActionListener(this);

text.setText("Test string....\n");
panel.add(scroller);
panelControl.add(b2);
panelControl.add(b1);

frame.getContentPane().add(BorderLayout.CENTER,panel);
frame.getContentPane().add(BorderLayout.SOUTH,panelControl);

frame.setSize(300,300);
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}

public void actionPerformed(ActionEvent e){
if( e.getSource() == b1 )
System.exit(0);
else
text.append("new line\n");
}

}


因為 JButton 所呼叫的 ActionListener 都會呼叫 actionPerfomed(),所以只好在此函式內判斷到底是哪個按鈕呼叫的,在依照不同的來源執行不同的動作。

public void actionPerformed(ActionEvent e){
if( e.getSource() == b1 )
System.exit(0);
else
text.append("new line\n");
}


但是這樣寫一點會使的整個程式架構混亂,尤其是按鈕需要值型的動作很複雜時,以後要維護程式碼會變的很麻煩,因此要換一個方式來做。

Java 中有個東西叫做 inner class,也就是 class 中的 class。 Inner class 可以存取 outer class 中的變數和函式,但是要注意的是 inner class 是當 outer class 被建立時才會跟著一起被建立,不會單獨存在。

這時要為每個 JButton 建議一個 inner class:

class buttonListenerEXIT implements ActionListener{
public void actionPerformed(ActionEvent e){
System.exit(0);
}
}

class buttonListenerNewLine implements ActionListener {
public void actionPerformed(ActionEvent e){
text.append("new line\n");
}
}


建立好 inner class 之後,要讓 JButton 的 ActionListener 會去呼叫寫好的函式:

b1.addActionListener(new buttonListenerEXIT());
b2.addActionListener(new buttonListenerNewLine());


改好之後,整個程式會變成這樣:

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;

public class panel0 {

JFrame frame = new JFrame();
JPanel panel = new JPanel();
JButton b1 = new JButton("Exit");
JButton b2 = new JButton("Add Line");
JTextArea text = new JTextArea(5,10);
JPanel panelControl = new JPanel();



public static void main(String[] arg){
panel0 gui = new panel0();
gui.go();
}

public void go(){

panel.setBackground(Color.gray);
panel.setLayout(new BoxLayout(panel,BoxLayout.Y_AXIS));

panelControl.setBackground(Color.gray);
panelControl.setLayout(new BoxLayout(panelControl,BoxLayout.X_AXIS) );

text.setLineWrap(true);
JScrollPane scroller = new JScrollPane(text);
scroller.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS);
scroller.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);

b1.addActionListener(new buttonListenerEXIT());
b2.addActionListener(new buttonListenerNewLine());

text.setText("Test string....\n");
panel.add(scroller);
panelControl.add(b2);
panelControl.add(b1);

frame.getContentPane().add(BorderLayout.CENTER,panel);
frame.getContentPane().add(BorderLayout.SOUTH,panelControl);

frame.setSize(300,300);
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}

class buttonListenerEXIT implements ActionListener{
public void actionPerformed(ActionEvent e){
System.exit(0);
}
}

class buttonListenerNewLine implements ActionListener {
public void actionPerformed(ActionEvent e){
text.append("new line\n");
}
}
}

沒有留言:

張貼留言