Java ActionListener 代码无法通过 JButton 生成"toggling"函数



按钮 B1 是一个没有文本的按钮,最初是黑色背景。 单击时,b1 的 ActionListener 会将其背景切换到图标。 当再次单击(或任何次数)时,b1 只是保持此图标,而我想要的功能是让它切换回黑色背景。 通过鼠标单击在黑色背景和此图标之间切换是我的目标。 但它只是保持原样作为这个图标。 下面发布了解决错误所需的代码片段。 如有任何见解,我将不胜感激。 IDE = 日食。 Box = Mac Retina。

 ...some code...
 JButton b1 = new JButton();
 ...some code...
 b1.setOpaque(true);
 b1.setBorderPainted(false);
 b1.setBackground(Color.BLACK);
 ...some code...
 icon = new ImageIcon[12]; //Behind the scenes here is that the source is randomly assigning
 icon[0] = alpha;          //images via an array.  This is not significant, but done for continuity.
 ...some code...
 b1.addActionListener(                                     //Anonymous Listener Class
        new ActionListener() {
           public void actionPerformed(ActionEvent e) {
              if(b1.getBackground().equals(Color.BLACK)) {
                 b1.setIcon(icon[0]);
                 b1.setBackground(Color.WHITE);
              }
              else {
                 b1.setIcon(null);
                 b1.setBackground(Color.BLACK);
              }               
           }});

我不会依赖JButtongetBackground()方法来知道它是否被单击,例如,可以在另一个会改变按钮背景的组件上调用java.awt.Component.setBackground

public void setBackground(Color c) {
    Color oldColor = background;
    ComponentPeer peer = this.peer;
    background = c;
    if (peer != null) {
        c = getBackground();
        if (c != null) {
            peer.setBackground(c);
        }
    }
    // This is a bound property, so report the change to
    // any registered listeners.  (Cheap if there are none.)
    firePropertyChange("background", oldColor, c);
}

所以我会做这样的事情:

b1.addActionListener(                                     //Anonymous Listener Class
        new ActionListener() {
           private isBlack = true;
           public void actionPerformed(ActionEvent e) {
              if(isBlack) {
                 b1.setIcon(icon[0]);
                 b1.setBackground(Color.WHITE);
              }else {
                 b1.setIcon(null);
                 b1.setBackground(Color.BLACK);
              }
              isBlack = !isBlack;
           }});

除了使用组件getBackground()作为状态指示器产生的代码异味之外,您上面提供的代码示例是正确的。您可以轻松尝试此SSCCE:

package swingtest;
import java.awt.Color;
import java.awt.event.ActionListener;
import java.net.MalformedURLException;
import java.net.URL;
import javax.swing.*;
public class SwingTest {
    public static void main( String[] args ) throws MalformedURLException {
        JFrame jf = new JFrame( "SwingTest" );
        JButton jb = new JButton( "test button" );
        jb.setOpaque( true );
        jb.setBorderPainted( false );
        jb.setBackground( Color.BLACK );
        URL url = new URL( "https://docs.oracle.com/javase/tutorial/images/oracle-java-logo.png" );
        ImageIcon imageIcon = new ImageIcon(url);
        jb.addActionListener( //Anonymous Listener Class
                new ActionListener() {
                    @Override
                    public void actionPerformed( java.awt.event.ActionEvent e ) {
                        if ( jb.getBackground().equals( Color.BLACK ) ) {
                            jb.setIcon( imageIcon );
                            jb.setBackground( Color.WHITE );
                        } else {
                            jb.setIcon( null );
                            jb.setBackground( Color.BLACK );
                        }
                    }
                } );
        jf.add( jb );
        jf.setSize( 800, 600 );
        jf.setVisible( true );
        jf.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
    }
}

它按预期工作,请自己尝试一下。因此,您的问题与您提供的代码无关。Xavier是对的,要么是其他东西搞砸了颜色/图标集(也许是另一个按钮?),要么你有一个与JButton和ActionListener完全无关的heisenbug。

事实证明,我发布的原始代码是可编译的,可运行的,并达到了预期的结果。 默认情况下,我的 Eclipse IDE 正在运行以前版本的功能失调代码,这是一个错误。 我对我的用户错误负责,我感谢人们生成的替代答案,这教会了我很多。 最后,我只是简单地提交了我最初为我的 assignmnet 发布的代码,因为它代表了我目前对 Java 的理解水平。

最新更新