2011-05-09 15 views
25

アクションリスナーで何が間違っているのか把握しようとしています。私は複数のチュートリアルに従っていますが、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、エラーを参照してください傾けるため、アクションリスナーが登録されることはありません。

+1

1)クラス名はEachWordUpperCaseである必要があります。 2)機能を追加しない限り、フレームを拡張しないでください。 3)拡張フレームの場合、おそらく 'main(String []) 'でインスタンス化する必要もないでしょう。4)1つのアクションリスナーを1つのGUIエレメントに追加するのではなく、巨大なif/elseカスケードを持つ 'actionPerformed(ActionEvent)'メソッド5)(4)の助言に従えば、問題はほとんどなくなります。 –

+0

アクションを使用することができます - 開いている一貫性(例のツールバーとボタン)で同じことを行う多くのUI要素に最適です。 http://docs.oracle.com/javase/tutorial/uiswing/misc/action.htmlを参照してください。 – tgkprog

答えて

32

静的メソッドには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) 
    } 

} 
+0

パーフェクト、それは私のためにそれをクリアしました。私は助けに感謝します – user519670

0

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

あなたの助けを大変ありがとう、これはたくさんの質問に答えました私のために。 – user519670

1

最初の問題はactionPerformed方法は、それへのアクセス権を持っていないのでbutton1は、main方法のローカル変数であるということです。

ActionListenerインターフェイスはクラスcalcで実装されていますが、このクラスのインスタンスはmainメソッドで作成されません。

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

+0

お手数をおかけしていただきありがとうございます。 – user519670

2

問題は、button1がローカル変数であることです。あなたは、あなたがactionListenerを追加する方法を変更するだけでそれを行うことができます。

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

それともbutton1グローバル変数を作ります。

+0

お手数をおかけしていただきありがとうございます。 – user519670

9

私のコメントに基づいてソースの変更された形式です。 GUIは、EDT上で更新された&である必要がありますが、それほど遠くまでは行きませんでした。

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); 
    } 
} 
+0

私の神よ、ありがとう、すべてのJavaコードが駄目だと思うようになってきた。 – drakonli

2

あなたはすぐに問題を解決する方法を聞かれましたが、ここではより重要な問題があると思います。

  • 慣例に従ってください。スローアウェイコードでさえも。つまり、クラス名の最初の場合を意味します。

  • 必要のないクラスを拡張しないでください。 JFrameはめったに拡張しないでください。実際、派生クラスのインスタンスは作成しません。

  • 複数のものを1つのクラスにまとめないでください。特に、一般的には、一度に1つのメインクラスまたはインタフェースをサブタイプ化するだけです(Comparableは含まれません)。

  • AWT Event Dispatch Thread(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します。

19

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

  • (あなたは使用がその横のボタンをクリックする代わりに、テキストフィールドに、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"); 
    } 
    } 
} 
+2

DontExtendJFrameAndDontImplementXXListenerAtTopLevel :-) – kleopatra

+0

なぜJFrameを拡張してはいけないのですか?私はいつも教えられてきました。 – Lucas

+3

@ルーカス一般的には、継承よりも構成が好都合です。 – Qwerky

0

、フレームにActionListenerにを追加し、ボタンを追加するまず、exend適切にスーパーとのJFrame()とコンストラクタ 。私が使用

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

いいえ(Calcをまったく使用していない点を除いて、実際に_run_あなたの例を参考にして気付いたことはありますか?)a)JFrameを拡張せず、代わりに使用します。b)xxListenerを実装せず、それ – kleopatra

0

- 私は、MVCのコンテキストから来てから、「e.getActionCommand()。(CharSecuence複数可)を含んでいる」、とボタンはViewクラスで宣言されたが、actionPerformedのコールが発生している中でコントローラ。

​​

私のコントローラクラスは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 
    } 
} 

を私は、この他の答えも有用であると思います。

関連する問題