web-dev-qa-db-ja.com

複数のボタンをリッスンするアクションリスナーを追加する方法

私はアクションリスナーで何が間違っているのかを理解しようとしています。複数のチュートリアルに従っていますが、アクションリスナーを使用しようとすると、netbeansとEclipseでエラーが発生します。

以下は、ボタンを機能させようとしている簡単なプログラムです。

何が間違っていますか?

_import Java.awt.event.ActionEvent;
import Java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;


public class calc extends JFrame implements ActionListener {



    public static void main(String[] args) {

        JFrame calcFrame = new JFrame();

        calcFrame.setSize(100, 100);
        calcFrame.setVisible(true);

        JButton button1 = new JButton("1");
        button1.addActionListener(this);

        calcFrame.add(button1);
    }

    public void actionPerformed(ActionEvent e) {
        if(e.getSource() == button1)
    }  

}
_

if(e.getSource() == button1)では_button1_を参照できないため、シンボルが見つからないというエラーが発生するため、アクションリスナーは登録されません。

28
user519670

静的メソッドにはthisポインターはありません。 (このコードがコンパイルされるとは思わない。)

main();のような静的メソッドでこれらのことを行うべきではありません。コンストラクターで設定します。実際に動作するかどうかを確認するためにこれをコンパイルまたは実行しませんでしたが、試してみてください。

public class Calc extends JFrame implements ActionListener {

    private Button button1;

    public Calc()
    {
        super();
        this.setSize(100, 100);
        this.setVisible(true);

        this.button1 = new JButton("1");
        this.button1.addActionListener(this);
        this.add(button1);
    }


    public static void main(String[] args) {

        Calc calc = new Calc();
        calc.setVisible(true);
    }

    public void actionPerformed(ActionEvent e) {
        if(e.getSource() == button1)
    }  

}
35
duffymo

アクションコマンドの使用について誰も言及していないことに驚いています。これは、ソースとリスナーを関連付ける非常に標準的な方法です。本当に便利なのは;

  • 同じことを行う必要がある複数のイベントソースがあります(たとえば、隣のボタンをクリックする代わりに、テキストフィールドでEnterキーを使用できるようにする場合)
  • イベントを生成するコンポーネントへの参照がありません

見る;

import Java.awt.FlowLayout;
import Java.awt.event.ActionEvent;    
import Java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JOptionPane;

public class DontExtendJFrame implements ActionListener {

  private enum Actions {
    HELLO,
    GOODBYE
  }

  public static void main(String[] args) {

    DontExtendJFrame instance = new DontExtendJFrame();

    JFrame frame = new JFrame("Test");
    frame.setLayout(new FlowLayout());
    frame.setSize(200, 100);

    JButton hello = new JButton("Hello");
    hello.setActionCommand(Actions.HELLO.name());
    hello.addActionListener(instance);
    frame.add(hello);

    JButton goodbye = new JButton("Goodbye");
    goodbye.setActionCommand(Actions.GOODBYE.name());
    goodbye.addActionListener(instance);
    frame.add(goodbye);

    frame.setVisible(true);
  }

  @Override
  public void actionPerformed(ActionEvent evt) {
    if (evt.getActionCommand() == Actions.HELLO.name()) {
      JOptionPane.showMessageDialog(null, "Hello");
    } else if (evt.getActionCommand() == Actions.GOODBYE.name()) {
      JOptionPane.showMessageDialog(null, "Goodbye");
    }
  }
}
20
Qwerky

これが私のコメントに基づいたソースの修正形式です。 EDTでGUIを構築および更新する必要があることに注意してください。ただし、ここまでは行きませんでした。

import Java.awt.event.ActionEvent;
import Java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JOptionPane;
import javax.swing.JFrame;

public class Calc {

    public static void main(String[] args) {

        JFrame calcFrame = new JFrame();

        // usually a good idea.
        calcFrame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);

        final JButton button1 = new JButton("1");
        button1.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent ae) {
                JOptionPane.showMessageDialog(
                    button1, "..is the loneliest number");
            }
        });

        calcFrame.add(button1);

        // don't do this..
        // calcFrame.setSize(100, 100);

        // important!
        calcFrame.pack();

        calcFrame.setVisible(true);
    }
}
9
Andrew Thompson

差し迫った問題を分類する方法を教えられましたが、ここにはもっと重要な問題があると思います。

  • 慣習に従ってください。使い捨てコードでも。つまり、クラス名の最初のケースを意味します。

  • 必要のないクラスを拡張しないでください。 JFrameはほとんど拡張されません。実際、派生クラスのインスタンスは作成しません!!!

  • たくさんのものを1つのクラスにまとめないでください。特に、通常は一度に1つのメインクラスまたはインターフェイスのみをサブタイプにする必要があります(Comparableなどは含まれません)。

  • AWTイベントディスパッチスレッド(EDT)上のSwing/AWT GUIを含め、常に対話します。見苦しくて冗長ですが、それはJavaです。

  • イベントのソースを確認するのはちょっとしたハックです。リスナーは小さいため、パフォーマンスの不十分な言い訳を主張することさえできません。

そう:

import Java.awt.event.ActionEvent;
import Java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;


public class Calc {
    public static void main(String[] args) {
        Java.awt.EventQueue.invokeLater(new Runnable() { public void run() {
            runEDT();
        }});
    }
    private static void runEDT() {
        assert Java.awt.EventQueue.isDispatchThread();

        JFrame frame = new JFrame();

        frame.setSize(100, 100);

        JButton button1 = new JButton("1");
        button1.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent event) {
                ...
            }
        });

        frame.add(button1);

        frame.setVisible(true);
    }
}

リスナー内の囲むメソッドから変数にアクセスする必要がある場合は、finalにします。

問題は、button1がローカル変数であることです。 actionListenerを追加する方法を変更するだけで実現できます。

button.addActionListener(new ActionListener() {  
            public void actionPerformed(ActionEvent e)
            {
                //button is pressed
                System.out.println("You clicked the button");
            }});

または、button1グローバル変数。

2
cb0

最初の問題は、button1mainメソッドのローカル変数であるため、actionPerformedメソッドはそれにアクセスできません。

2番目の問題は、ActionListenerインターフェイスがクラスcalcによって実装されますが、このクラスのインスタンスがmainメソッドで作成されないことです。

望むことをする通常の方法は、calcのインスタンスを作成し、button1calcクラスのフィールド。

1
Laurent Pireyn

ここには良い答えがありますが、multipleボタンをリッスンするアクションリスナーを追加するというよりグローバルなポイントに対処しましょう。

2つの一般的なアプローチがあります。

共通アクションリスナーの使用

actionPerformed(ActionEvent e)実装でアクションのソースを取得できます:

JButton button1, button2; //your button

@Override
public void actionPerformed(ActionEvent e) {

    JButton actionSource = (JButton) e.getSource();

    if(actionSource.equals(button1)){
        // YOU BUTTON 1 CODE HERE
    } else if (actionSource.equals(button2)) {
        // YOU BUTTON 2 CODE HERE
    }
}

ActionCommandの使用

このアプローチでは、ボタンのactionCommandフィールドを設定します。これにより、後でswitchを使用できるようになります。

button1.setActionCommand("actionName1");
button2.setActionCommand("actionName2");

以降:

@Override
public void actionPerformed(ActionEvent e) {
    String actionCommand = ((JButton) e.getSource()).getActionCommand();

    switch (actionCommand) {
        case "actionName1": 
            // YOU BUTTON 1 CODE HERE
        break;
        case "actionName2": 
            // YOU BUTTON 2 CODE HERE
        break;
    }
}

JFrameボタン、リスナー、およびフィールドの詳細 をご覧ください。

0
Johnny

Mainメソッドでbutton1を宣言しているため、actionPerformでアクセスできません。クラス内でグローバルにする必要があります。

 JButton button1;
 public static void main(String[] args) {

    JFrame calcFrame = new JFrame();

    calcFrame.setSize(100, 100);
    calcFrame.setVisible(true);

    button1 = new JButton("1");
    button1.addActionListener(this);

    calcFrame.add(button1);
}

public void actionPerformed(ActionEvent e) {
    if(e.getSource() == button1)
}
0
Harry Joy

「e.getActionCommand()。contains(CharSecuence s)」を使用しています。これは、MVCコンテキストから来ており、ButtonがViewクラスで宣言されているが、actionPerformed呼び出しがコントローラーで発生するためです。

public View() {
    ....
    buttonPlus = new Button("+");
    buttonMinus = new Button("-");
    ....
}

public void addController(ActionListener controller) {
    buttonPlus.addActionListener(controller);
    buttonMinus.addActionListener(controller);
}

コントローラークラスはActionListenerを実装するため、actionPerformedをオーバーライドする場合:

public void actionPerformed(ActionEvent e) {
    if(e.getActionCommand().contains("+")) {
        //do some action on the model
    } else if (e.getActionCommand().contains("-")) {
       //do some other action on the model
    }
}

この他の回答も役立つことを願っています。

0
Omar N

最初に、super()とコンストラクタを使用してJFrameを適切に拡張してから、フレームにactionlistenerを追加し、ボタンを追加します。

import Java.awt.event.ActionEvent;
import Java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;


public class Calc extends JFrame implements ActionListener {
    JButton button1 = new JButton("1");
    JButton button2 = new JButton("2");

    public Calc()
    {
         setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
         setSize(100, 100);
         button1.addActionListener(this);
         button2.addActionListener(this);
         calcFrame.add(button1);
         calcFrame.add(button2);
    }
    public void actionPerformed(ActionEvent e)
    {
        Object source = e.getSource();
        if(source == button1)
        {
            \\button1 code here
        } else if(source == button2)
        {
            \\button2 code here
        }
    } 
    public static void main(String[] args)
    {

        JFrame calcFrame = new JFrame();
        calcFrame.setVisible(true);
    }
}
0
Jon Takagi