尝试将ActionListener添加到JButtons

我无法弄清楚如何将Actionlisteners添加到JButton ,任何帮助将不胜感激。

 public class Translator extends JPanel implements MouseListener, ActionListener { private JButton french = new JButton(); private JButton german = new JButton(); private JButton irish = new JButton(); public Translator(){ french = new JButton("French"); german = new JButton("German"); irish = new JButton("Irish"); setLayout(new GridLayout(2,1)); buttonPanel.setLayout(new GridLayout(1,3)); buttonPanel.add(french); buttonPanel.add(german); buttonPanel.add(irish); } @Override public void actionPerformed(ActionEvent e) { // TODO Auto-generated method stub } @Override public void mouseClicked(MouseEvent e) { // TODO Auto-generated method stub } @Override public void mouseEntered(MouseEvent e) { // TODO Auto-generated method stub } } 

有很多方法可以将ActionListener添加到给定的JComponent (支持它的使用)。 我在代码片段中添加了一些注释,以帮助解释它们更好一些,以及评论中的一些链接以供将来参考。

1.) 如果类实现了ActionListener接口,即类本身包含actionPerformed(...)方法 ,那么就可以这样做:

 import java.awt.*; import java.awt.event.*; import javax.swing.*; public class Skeleton implements ActionListener { private JFrame frame; private JPanel contentPane; private JButton button; private void displayGUI() { frame = new JFrame("Skeleton"); /* * EXIT_ON_CLOSE is same as putting System.exit(0), * which in some sense, doesnot allows one's * application to terminate graciously. */ frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); contentPane = new JPanel(); button = new JButton("This is a button."); /* * This is one way of attaching an ActionListener * to the JButton, but the main disadvantage of * this approach is, it breaks encapsulation, * as you can see the public method, actionPerformed(), * is lying free to be accessed by any code outside * the scope of the class */ button.addActionListener(this); contentPane.add(button); frame.setContentPane(contentPane); frame.pack(); frame.setLocationByPlatform(true); frame.setVisible(true); } public static void main(String[] args) { Runnable runnable = new Runnable() { @Override public void run() { new Skeleton().displayGUI(); } }; EventQueue.invokeLater(runnable); } @Override public void actionPerformed(ActionEvent e) { JOptionPane.showMessageDialog(frame, "BINGO!", "Information: ", JOptionPane.INFORMATION_MESSAGE); } } 

2.) 如果一个人不想创建不必要的class文件。 然后可以使用这种方法,使用EventHandler

 import java.awt.*; import java.awt.event.*; import java.beans.EventHandler; import javax.swing.*; public class Example1 { private JFrame frame; private JPanel contentPane; private JButton button; private void displayGUI() { frame = new JFrame("Skeleton"); /* * EXIT_ON_CLOSE is same as putting System.exit(0), * which in some sense, doesnot allows one's * application to terminate graciously. */ frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); contentPane = new JPanel(); button = new JButton("This is a button."); /* * This is another way of attaching * an ActionListener to the JButton, * the main advantage of this approach * is, that one does not have to create * a new class to handle events * More info regarding the use of this * approach, can be found on this link : * http://docs.oracle.com/javase/tutorial/uiswing/events/generalrules.html */ button.addActionListener((ActionListener) EventHandler.create(ActionListener.class , Example1.this, "buttonAction", "")); contentPane.add(button); frame.setContentPane(contentPane); frame.pack(); frame.setLocationByPlatform(true); frame.setVisible(true); } public static void main(String[] args) { Runnable runnable = new Runnable() { @Override public void run() { new Example1().displayGUI(); } }; EventQueue.invokeLater(runnable); } public void buttonAction(ActionEvent e) { JOptionPane.showMessageDialog(frame, "BINGO!", "Information: ", JOptionPane.INFORMATION_MESSAGE); } } 

3.) 如果一个人更关心Encapsulation的概念,那么这种方法是有益的:

 import java.awt.*; import java.awt.event.*; import javax.swing.*; public class Example2 { private JFrame frame; private JPanel contentPane; private JButton button; private ActionListener buttonActions = new ActionListener() { @Override public void actionPerformed(ActionEvent ae) { JOptionPane.showMessageDialog(frame, "BINGO!", "Information: ", JOptionPane.INFORMATION_MESSAGE); } }; private void displayGUI() { frame = new JFrame("Skeleton"); /* * EXIT_ON_CLOSE is same as putting System.exit(0), * which in some sense, doesnot allows one's * application to terminate graciously. */ frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); contentPane = new JPanel(); button = new JButton("This is a button."); /* * This is another way of attaching * an ActionListener to the JButton, * the main advantage of this approach * is, it adheres to encapsulation. */ button.addActionListener(buttonActions); contentPane.add(button); frame.setContentPane(contentPane); frame.pack(); frame.setLocationByPlatform(true); frame.setVisible(true); } public static void main(String[] args) { Runnable runnable = new Runnable() { @Override public void run() { new Example2().displayGUI(); } }; EventQueue.invokeLater(runnable); } } 

4.) 如果更倾向于创建匿名类,则可以使用以下方法:

 import java.awt.*; import java.awt.event.*; import javax.swing.*; public class Example3 { private JFrame frame; private JPanel contentPane; private JButton button; private void displayGUI() { frame = new JFrame("Skeleton"); /* * EXIT_ON_CLOSE is same as putting System.exit(0), * which in some sense, doesnot allows one's * application to terminate graciously. */ frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); contentPane = new JPanel(); button = new JButton("This is a button."); /* * This is the fourth way of attaching * an ActionListener to the JButton, * the main advantage of this approach * is, it adheres to encapsulation, the * public method remains hidden * inside the Anonymous Class * More info can be found on this link : * http://docs.oracle.com/javase/tutorial/java/javaOO/anonymousclasses.html * The main disadvantage of this approach is * that it doesnot gives you the privilege * of separation of concerns, which can * be done using the fifth approach, * which is MVC - Pattern (Model-View-Controller) * and moreover, it creates a hell lot of classes, in * your project, which can lead to extra overhead */ button.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent ae) { JOptionPane.showMessageDialog(frame, "BINGO!", "Information: ", JOptionPane.INFORMATION_MESSAGE); } }); contentPane.add(button); frame.setContentPane(contentPane); frame.pack(); frame.setLocationByPlatform(true); frame.setVisible(true); } public static void main(String[] args) { Runnable runnable = new Runnable() { @Override public void run() { new Example3().displayGUI(); } }; EventQueue.invokeLater(runnable); } } 

编辑:

5.) 这种方法包括使用Action而不是ActionListener 这将用于在各种JComponent之间共享相同的function,从而导致代码可重用性

 import java.awt.*; import java.awt.event.*; import javax.swing.*; public class Example4 { private JFrame frame; private JPanel contentPane; private JMenuItem showMenuItem; private JButton button; private Action myActions; /* * This approach is basically used, when * one wants to share the same functionality * of different JComponents among each other, * without writing redundant codes for each * one of those components. Here JMenuItem * and JButton are both using the same * functionality, to perform the same task. * More info can be found on this link: * http://docs.oracle.com/javase/tutorial/uiswing/misc/action.html */ private class MyActions extends AbstractAction { public MyActions(String title, String desc) { super(title); putValue(SHORT_DESCRIPTION, desc); } @Override public void actionPerformed(ActionEvent ae) { JOptionPane.showMessageDialog(frame, "BINGO!", "Information: ", JOptionPane.INFORMATION_MESSAGE); } } private void displayGUI() { frame = new JFrame("Skeleton"); /* * EXIT_ON_CLOSE is same as putting System.exit(0), * which in some sense, doesnot allows one's * application to terminate graciously. */ frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); contentPane = new JPanel(); button = new JButton("This is a button."); myActions = new MyActions("Show", "A small description"); button.setAction(myActions); contentPane.add(button); frame.setJMenuBar(getJMenuBar()); frame.setContentPane(contentPane); frame.pack(); frame.setLocationByPlatform(true); frame.setVisible(true); } private JMenuBar getJMenuBar() { JMenuBar menuBar = new JMenuBar(); JMenu fileMenu = new JMenu("File"); showMenuItem = new JMenuItem(myActions); fileMenu.add(showMenuItem); menuBar.add(fileMenu); return menuBar; } public static void main(String[] args) { Runnable runnable = new Runnable() { @Override public void run() { new Example4().displayGUI(); } }; EventQueue.invokeLater(runnable); } } 
 french.addActionListener(an_instance_of_the_class_where_actionPerformed_is); 

正如我在编辑后看到的那样,这就是this

另外,请参阅此示例以及Web角落中的一些教程文本

我认为对教程和许多示例的引用具有高度相关性。

 button.addActionListener(); 

在你的情况下,它将是:

 french.addActionListener(this); 

如果要对所有三个按钮使用相同的ActionListener,可以使用ActionEvent e的getSource()函数来检测实际按下的按钮。

如果您使用的是Java8,可以试试这个。

 JButton french = new JButton("French"); french.addActionListener(new ActionListener(){ @Override public void actionPerformed(ActionEvent ae){ System.out.println("Button french clicked!"); } }); french.addActionListener(button -> System.out.println("Button Click listener...")); JFrame frame = new JFrame("Button Listener Test"); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.add(french, BorderLayout.CENTER); frame.setSize(250, 250); frame.setVisible(true); 

显然答案是将this放入addActionListener方法中。

addActionListener方法将实现 ActionListener接口的对象作为参数,此接口强制您实现/置于您的代码中的actionPerformed方法,当被动作被触发到分配的组件时,该方法被调用。

因此,将this放在您的方法中,它将在您传递的对象内搜索,在我们的例子中,搜索actionPerformed方法的Translator对象并调用它。

 this.french.addActionListener(this); 

当然,为了工作,缺少很多代码。

我真的很喜欢@Sandeep的答案,使用lambda表达式。 您可以在下面看到完整的示例。

 import java.awt.GridLayout; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import javax.swing.JButton; import javax.swing.JFrame; import javax.swing.JPanel; public class Translator extends JPanel implements ActionListener { private JButton french = new JButton(); private JButton german = new JButton(); private JButton irish = new JButton(); @SuppressWarnings("empty-statement") public Translator(){ french = new JButton("French"); german = new JButton("German"); irish = new JButton("Irish"); // setLayout(new GridLayout(2,1)); this.setLayout(new GridLayout(1,3)); this.add(french); this.add(german); this.add(irish); ActionListener ac = (ActionEvent ae) -> { System.out.println(((JButton) ae.getSource()).getText()); }; this.french.addActionListener(ac); this.german.addActionListener(ac); this.irish.addActionListener(ac); this.irish.addActionListener(Translator.this); } @Override public void actionPerformed(ActionEvent e) { System.out.println(((JButton) e.getSource()).getText()); } public static void main(String[] args) { JFrame jframe = new JFrame("StackOverflow"); jframe.add(new Translator()); jframe.pack(); jframe.setLocationRelativeTo(null); jframe.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); jframe.setVisible(true); } } 
 JButton button = new JButton("Button"); button.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { //To-Do //Button clicked }); 

希望这有帮助,它相对简单! 您只需要将ActionListener添加到所需的JButton即可

为了让您更广泛地了解如何在案例场景中实现它,我想在按下按钮后运行新的GUI框架:

 startNewFrame.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { System.out.println("Starting new frame"); SwingUtilities.invokeLater(new Runnable() { @Override public void run() { NewFrame newFrame = new NewFrame(); newFrame.setVisible(true); dispose();//Disposes of current frame } }); } });