【问题标题】:Finding the right argument for addActionListener为 addActionListener 找到正确的参数
【发布时间】:2017-03-29 07:18:18
【问题描述】:

我正在尝试制作一个在按下时切换按钮状态(更改颜色和文本)的按钮。但我无法让 addActionListener 工作,也无法从我的主类中找到 ToggleState 方法。我是 Java 新手,非常感谢您的帮助。

我得到了错误 - “AbstractButton 类型中的方法 addActionListener(ActionListener) 不适用于参数” - “ActionListener 无法解析为类型”

package Grafiktest;

import javax.swing.*;
import java.awt.*;

public class coolgrafik extends JFrame implements ActionListener {

private static final long serialVersionUID = 1L;
private JPanel panel;
private JLabel label;

public coolgrafik(){

    //super(title);
    setSize(400,60);
    setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

    panel = new JPanel();
    panel.setBackground(Color.GRAY);
    label = new JLabel("test");
    panel.add(label);

    MyButton button = new MyButton(Color.green, Color.red, "RUN","STOP");
    panel.add(button);
    button.addActionListener(this);

    add(panel);
}

public static void main(String[] args){
    new coolgrafik().setVisible(true);
    //toggleState(Color.green, Color.red, "RUN","STOP");
}

public void actionPerformed(ActionEvent e) {
    toggleState(Color.green, Color.red, "RUN","STOP");
}
}

这是按钮类

package Grafiktest;

import javax.swing.*;
import java.awt.*;

public class MyButton extends JButton{

private static final long serialVersionUID = 1L;

public MyButton(Color c1, Color c2, String s1, String s2){

    setText(s1);
    setForeground(c1);
    setBackground(c1);
    setOpaque(true);

}

public void toggleState(Color c1, Color c2, String s1, String s2){

    setText(s2);
    setForeground(c2);
    setBackground(c2);
    setOpaque(true);

}

}

【问题讨论】:

标签: java jframe jbutton actionlistener


【解决方案1】:

让我们停下来想一想你想要做什么。您想在按下按钮时更改按钮的状态。

真正的问题是,谁真正负责这样做?任何监视按钮的ActionListener 都应该专注于执行他们需要做的工作,而不是管理按钮,当按钮上附加了多个ActionListener 时会发生什么?那么谁来负责呢?

如果我们让按钮自我管理会怎样?也就是说,按钮会监控自己并相应地更新其状态

因为无论如何您都需要管理选定状态,所以我使用了JToggleButton,因为它在内部具有“选定”/“未选定”状态。

public class MyButton extends JToggleButton {

    private static final long serialVersionUID = 1L;

    public class State {
        public Color color;
        public String text;

        public State(Color color, String text) {
            this.color = color;
            this.text = text;
        }

    }

    private final State unselectedState;
    private final State selectedState;

    public MyButton(Color c1, Color c2, String s1, String s2) {

        selectedState = new State(c1, s1);
        unselectedState = new State(c2, s2);

        setContentAreaFilled(false);
        setBorderPainted(false);
        setFocusPainted(false);
        setOpaque(true);

        toggleState();

        getModel().addChangeListener(new ChangeListener() {
            @Override
            public void stateChanged(ChangeEvent e) {
                toggleState();
            }
        });

    }

    public void toggleState() {

        State state = !getModel().isSelected() ? selectedState : unselectedState;

        setText(state.text);
        setForeground(Color.WHITE);
        setBackground(state.color);

    }
}

基本上所有这些都会根据ButtonModelselected 状态配置按钮。

您可以使用 ActionListener 并以类似方式将其直接注册到按钮本身,但您需要管理它使用的状态

【讨论】:

    【解决方案2】:

    完成@Japu_D_Cret 的评论:

    您要么需要将 toggleState 方法设为静态才能像在 actionPerformed 方法中那样调用它,或者使用按钮来调用它:

    button.toggleState(Color.green, Color.red, "RUN","STOP");
    

    因为它是在您的 MyButton 类中定义的方法,而不是在您的 coolgrafik 类中。

    【讨论】:

      【解决方案3】:

      “AbstractButton 类型中的方法 addActionListener(ActionListener) 不适用于参数”-“ActionListener 无法解析为类型”

      您没有导入 ActionListener 类,因为它不在 java.awt.* 中,而是在 java.awt.event.ActionListener 中 - 供参考 https://docs.oracle.com/javase/7/docs/api/java/awt/event/ActionListener.html

      但我仍然无法使用 actionperformer 中的 toggleState 方法。怎么会?

      在您的void actionPerformed(ActionEvent) 中,您尝试调用一个名为void toggleState(Color,Color,String,String) 的方法 - 但它没有在同一个类中声明,也不是静态导入的。

      您显然想在您的对象button 上调用MyButtontoggleState 方法,为此您必须调用该对象上的方法,例如button.toggeState(...) 这也不会直接起作用,因为您的对象button 仅在您的构造函数中是已知的,并且您必须向您的coolgrafik 类添加一个对象属性,就像您对面板所做的那样 - 那么它应该可以正常工作

      这里是您需要在 coolgrafik 类中更改的代码片段

      属性:

      private JPanel panel;
      private JLabel label;
      private MyButton button;
      

      在你的coolgrafik构造函数中

      //...
      this.button = new MyButton(Color.green, Color.red, "RUN","STOP");
      this.panel.add(this.button);
      this.button.addActionListener(this);
      //...
      

      和你的 actionPerformed 方法

      public void actionPerformed(ActionEvent e) {
          button.toggleState(Color.green, Color.red, "RUN","STOP");
      }
      

      【讨论】:

      • 成功了!但我不完全明白如何。我已阅读有关 this 关键字的信息,但我看不出它在这种情况下有何帮助。你介意给我一个解释吗?
      • @G.Dog this.button 表示您明确要使用对象属性button,您也可以只使用button 并获得相同的结果,只要方法执行也不要声明名称为 button 的变量。在我看来,this-keyword 的符号更清晰,更不可能破坏你的代码,因为它总是使用 object 属性。但它不会让你的代码变得更慢,也不会让它变得更快,它只是使用起来非常方便,而且不那么随意——另见stackoverflow.com/questions/3728062/…
      • 好的,我现在明白了。但是我将 ActionListener 移到了 MyButton 类。我可以使用 MyButton 构造函数从 coolgrafik 构造函数中的 MyButton 调用中获取的参数来调用 actionPerformed 方法吗?例如“toggleState(c1, c2, s1, s2)”
      • @G.Dog 你可以 - 要做到这一点,你必须将对象保存为属性,你在构造函数中获得 - 所以为每种颜色和字符串添加一个属性(@987654338 @) 并将值分配给构造函数中的该属性。然后,如果您想使用这些保存的对象调用 toggleState,您可以使用 toggeState(this.c1, this.s1, ...)
      • 我将 (private Color c1; private String s1; //...) 定义为构造函数上的字段,然后尝试在构造函数中为它们赋予值 Color c1 = c1;颜色 c2 = this.c2 等,但这是不可能的。我误会你了吗?错误重复局部变量 c1
      猜你喜欢
      • 2013-09-28
      • 1970-01-01
      • 1970-01-01
      • 2017-01-15
      • 2017-11-12
      • 2022-08-22
      • 2023-01-12
      • 2013-05-23
      • 1970-01-01
      相关资源
      最近更新 更多