我想弄清楚我对动作听众做错了什么。我正在学习多个教程,但是当我尝试使用动作监听器时,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
,错误说无法找到符号。
答案 0 :(得分:35)
静态方法中没有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)
}
}
答案 1 :(得分:20)
我很惊讶没有人提到使用动作命令。这是关联源和侦听器的非常标准的方式。它非常有用;
见
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 :(得分:9)
以下是基于我的评论的源的修改形式。注意,应该构建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);
}
}
答案 3 :(得分:3)
你被告知如何对你眼前的问题进行排序,但我认为这里有更重要的问题。
坚持惯例。即使是丢弃代码。这意味着类名的初始案例。
不要扩展您不需要的类。 JFrame
应该很少延长。实际上,您没有创建派生类的实例!!!
不要将一堆东西捆绑到一个类中。特别是,您通常一次只能对一个主类或接口进行子类型化(不包括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
。
答案 4 :(得分:2)
问题是button1是一个局部变量。你可以通过改变添加actionListener的方式来实现。
button.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e)
{
//button is pressed
System.out.println("You clicked the button");
}});
或者您将button1
设为全局变量。
答案 5 :(得分:1)
第一个问题是button1
是main
方法的局部变量,因此actionPerformed
方法无法访问它。
第二个问题是ActionListener
接口是由类calc
实现的,但是在main
方法中没有创建此类的实例。
执行所需操作的常用方法是创建calc
的实例,并将button1
作为calc
类的字段。
答案 6 :(得分: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)
}
答案 7 :(得分:0)
首先,使用super()和构造函数正确扩展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);
}
}
答案 8 :(得分:0)
我使用“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
}
}
我希望其他答案也很有用。
答案 9 :(得分:0)
这里有很好的答案,但让我来谈谈添加可监听多个按钮的动作监听器的更全局的点。
有两种流行的方法。
使用通用操作侦听器
您可以在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;
}
}
答案 10 :(得分:0)
这是一个很老的问题。我想没人再在乎了。但是我想发表我的方法,以防对某人有所帮助。
使用我的方法,您可以以“经典方式”编写按钮单击事件处理程序,就像在VB或MFC中一样;)
假设我们有一个包含2个按钮的框架窗口类:
class MainWindow {
Jbutton searchButton;
Jbutton filterButton;
}
您可以使用我的“ router”类将事件路由回您的MainWindow类:
class MainWindow {
JButton searchButton;
Jbutton filterButton;
ButtonClickRouter buttonRouter = new ButtonClickRouter(this);
void initWindowContent() {
// create your components here...
// setup button listeners
searchButton.addActionListener(buttonRouter);
filterButton.addActionListener(buttonRouter);
}
void on_searchButton() {
// TODO your handler goes here...
}
void on_filterButton() {
// TODO your handler goes here...
}
}
你喜欢吗? :)
如果您喜欢这种方式并且讨厌Java的匿名子类方式,那么您和我一样大。 “ addActionListener(new ActionListener {...})”的问题在于,它将所有按钮处理程序压缩到一个外部方法中,该外部方法使程序看起来更有线。 (以防您在一个窗口中有许多按钮)
最后,路由器类别在下面。您可以将其复制到程序中,而无需进行任何更新。
仅需提一下:此路由器类必须可以访问按钮字段和事件处理程序方法!简而言之,如果将此路由器类复制到程序的同一程序包中,则按钮字段和方法必须是程序包可访问的。否则,它们必须是公开的。
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class ButtonClickRouter implements ActionListener {
private Object target;
ButtonClickRouter(Object target) {
this.target = target;
}
@Override
public void actionPerformed(ActionEvent actionEvent) {
// get source button
Object sourceButton = actionEvent.getSource();
// find the corresponding field of the button in the host class
Field fieldOfSourceButton = null;
for (Field field : target.getClass().getDeclaredFields()) {
try {
if (field.get(target).equals(sourceButton)) {
fieldOfSourceButton = field;
break;
}
} catch (IllegalAccessException e) {
}
}
if (fieldOfSourceButton == null)
return;
// make the expected method name for the source button
// rule: suppose the button field is 'searchButton', then the method
// is expected to be 'void on_searchButton()'
String methodName = "on_" + fieldOfSourceButton.getName();
// find such a method
Method expectedHanderMethod = null;
for (Method method : target.getClass().getDeclaredMethods()) {
if (method.getName().equals(methodName)) {
expectedHanderMethod = method;
break;
}
}
if (expectedHanderMethod == null)
return;
// fire
try {
expectedHanderMethod.invoke(target);
} catch (IllegalAccessException | InvocationTargetException e) { }
}
}
我是Java(不是编程)的初学者,所以上面的代码中可能有什么不合适的内容。请在使用前对其进行检查。