Как добавить прослушиватель действий, который прослушивает несколько кнопок
Я пытаюсь понять, что я делаю неправильно с прослушивателями действий. Я следую нескольким учебникам, и все же 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
В статическом методе нет указателя 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)
}
}
Ответ 2
Я поражен тем, что никто не упомянул об использовании команды action. Это довольно стандартный способ связывания источников и слушателей. Его действительно полезно, если:
- у вас есть несколько источников событий, которые должны делать то же самое (например, если вы хотите, чтобы использование могло нажимать клавишу ввода в текстовом поле в качестве альтернативы нажатию кнопки рядом с ней)
- у вас нет ссылки на компонент, генерирующий событие
см;
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");
}
}
}
Ответ 3
Вот модифицированная форма источника, основанная на моем комментарии. Обратите внимание, что графические интерфейсы должны быть построены и обновлены на 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);
}
}
Ответ 4
Вам рассказали, как сортировать вашу ближайшую проблему, но я думаю, что здесь есть более важные проблемы.
-
придерживаться условных обозначений. Даже для кода выброса. Это означает начальные случаи для имен классов.
-
Не расширяйте классы, которые вам не нужны. JFrame
редко следует расширять. Фактически, вы не создаете экземпляр вашего производного класса!!!
-
Не связывайте кучу вещей в один класс. В частности, вы должны обычно только подтип не более одного основного класса или интерфейса за один раз (такие вещи, как Comparable
не включены).
-
Всегда взаимодействуйте, включая конструкцию, Swing/AWT GUI на AWT Event Dispatch Thread (EDT). Это уродливое и многословное, но для вас 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
.
Ответ 5
Проблема в том, что button1 является локальной переменной. Вы можете сделать это, просто изменив способ добавления actionListener.
button.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e)
{
//button is pressed
System.out.println("You clicked the button");
}});
Или вы делаете button1
глобальную переменную.
Ответ 6
Первая проблема заключается в том, что button1
является локальной переменной метода main
, поэтому метод actionPerformed
не имеет к ней доступа.
Вторая проблема заключается в том, что интерфейс ActionListener
реализуется классом calc
, но экземпляр этого класса не создается в методе main
.
Обычный способ сделать то, что вам нужно, - создать экземпляр calc
и сделать button1
поле класса calc
.
Ответ 7
Вы объявляете 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)
}
Ответ 8
Во-первых, правильно запустите JFrame с помощью super() и конструктора
затем добавьте исполнители действий в рамку и добавьте кнопки.
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);
}
}
Ответ 9
Я использую "e.getActionCommand(). содержит (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
}
}
Я надеюсь, что этот другой ответ также будет полезен.
Ответ 10
Здесь есть хорошие ответы, но позвольте мне обратиться к более глобальному моменту добавления слушателя действия, который слушает несколько кнопок.
Есть два популярных подхода.
Использование прослушивателя общего действия
Вы можете получить источник действия в своей реализации 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, слушателях и полях.