【问题标题】:Calling non-local variable in ActionPerformed在 ActionPerformed 中调用非局部变量
【发布时间】:2019-07-08 21:46:53
【问题描述】:

我有一个随机涂有 3 种不同颜色(蓝色、红色和绿色)的圆圈和 3 个具有相同颜色(蓝色、红色和绿色)的按钮,如果圆圈是红色并且我按下红色按钮,我需要显示如果您选择了错误的颜色,则会出现在您赢得的标签中。这很简单,但我无法从paintComponent 调用ActionPerformed 变量(即与按钮匹配的颜色)。也为我的语言感到抱歉。

这是包含 2 个类的代码:

PaintPanel.class

public class PaintPanel extends JPanel implements ActionListener {

int x = 200, y = 250;
private JButton b1 = new JButton("BLUE");
private JButton b2 = new JButton("RED");
private JButton b3 = new JButton("GREEN");
 JLabel label = new JLabel("Choose the right Color");
 JPanel subPanel = new JPanel();
private Color[] colors;

public PaintPanel() {

    setLayout(new BorderLayout());
    setPreferredSize(new Dimension(440, 440));
    add(label, BorderLayout.NORTH);
    b1.addActionListener(this);
    b2.addActionListener(this);
    b3.addActionListener(this);
    subPanel.add(b1);
    b1.setForeground(Color.BLUE);
    subPanel.add(b2);
    b2.setForeground(Color.RED);
    subPanel.add(b3);
    b3.setForeground(Color.GREEN);
    add(subPanel, BorderLayout.SOUTH);

}

@Override
public void paintComponent(Graphics g) {
    super.paintComponent(g);
    Color[] colors = new Color[3];

    colors[0] = Color.BLUE;
    colors[1] = Color.RED;
    colors[2] = Color.GREEN;

    Color c1 = colors[randInt(colors.length)];


    g.setColor(c1);
    /* this.colors.equals(c1); !!!! HERE I TRIED !!!*/
    g.fillOval(x, y, 30, 30);

}

private int randInt(int length) {
    // TODO Auto-generated method stub
    Random rand = new Random();
    int randomColor = rand.nextInt(length);
    return randomColor;
}

@Override
public void actionPerformed(ActionEvent e) {
    if (e.getSource() == b1) {
        if (Color.BLUE.equals(colors)) {
            label.setText("You WIN");
        }
    }else {
        label.setText("You LOSE");
    } 
    if (e.getSource() == b2) {

    }
    if (e.getSource() == b3) {

    }
}
}

另一个 - DrawCircle.class -

public class DrawCircle extends JFrame {

private JPanel painted;

public DrawCircle() {
    painted = new PaintPanel();
    setDefaultCloseOperation(EXIT_ON_CLOSE);
    setLayout(new FlowLayout());
    setBounds(0, 0, 800, 540);
    add(painted);
    setVisible(true);
}

public static void main(String[] args) {
    new DrawCircle();

}

}

【问题讨论】:

    标签: java swing awt actionlistener


    【解决方案1】:

    请注意:您不能从静态上下文访问非静态方法。考虑将您的 DrawCircle() 方法放在一个单独的类中。创建该类的实例并从该实例调用DrawCircle()

    关于PaintPanel.class,请注意paintComponent() 被非常频繁地调用,而不仅仅是在初始化时调用。您生成的颜色需要保存在actionPerformed() 可以访问的位置。考虑在您的班级结构中创建一个Color tmp 成员并从那里引用您的正确答案。此外,您似乎错过了对UpdateUI() 的呼叫。这段代码并不完美,但运行良好。就个人而言,我会找到一种不同的方法来生成新颜色,而不是覆盖paintComponent(),但是如果你需要它,这个例子应该会很有帮助。在下面评论改进:

    package com.company;
    
    import javax.swing.*;
    import java.awt.*;
    import java.awt.event.ActionEvent;
    import java.awt.event.ActionListener;
    import java.util.Random;
    
    public class PaintPanel extends JPanel implements ActionListener
    {
    
        int x = 200, y = 250;
        private JButton b1 = new JButton("BLUE");
        private JButton b2 = new JButton("RED");
        private JButton b3 = new JButton("GREEN");
        JLabel label = new JLabel("Choose the right Color");
        JPanel subPanel = new JPanel();
        private Color[] colors;
        Color tmp = null;
    
        public PaintPanel()
        {
    
            setLayout(new BorderLayout());
            setPreferredSize(new Dimension(440, 440));
            add(label, BorderLayout.NORTH);
            b1.addActionListener(this);
            b2.addActionListener(this);
            b3.addActionListener(this);
            subPanel.add(b1);
            b1.setForeground(Color.BLUE);
            subPanel.add(b2);
            b2.setForeground(Color.RED);
            subPanel.add(b3);
            b3.setForeground(Color.GREEN);
            add(subPanel, BorderLayout.SOUTH);
    
        }
    
        @Override
        public void paintComponent(Graphics g)
        {
            super.paintComponent(g);
    
            colors = new Color[3]; //Referencing Class member colors instead of local variable
            colors[0] = Color.BLUE;
            colors[1] = Color.RED;
            colors[2] = Color.GREEN;
    
            tmp = colors[randInt(colors.length)]; //Read into a class member instead of a local variable
            g.setColor(tmp);
            System.out.println("Paint Triggered. New Color is: " + tmp.toString()); //todo remove this debugging line
            g.fillOval(x, y, 30, 30);
        }
    
        private int randInt(int length)
        {
            // TODO Auto-generated method stub
            Random rand = new Random();
            int randomColor = rand.nextInt(length);
            return randomColor;
        }
    
        @Override
        public void actionPerformed(ActionEvent e)
        {
            if (e.getSource() == b1) {
                if (Color.BLUE.equals(tmp)) {
                    label.setText("You WIN");
                } else {
                    label.setText("You Loose");
                }
            } else if (e.getSource() == b2) {
                if (Color.RED.equals(tmp)) {
                    label.setText("You WIN");
                } else {
                    label.setText("You Loose");
                }
            } else if (e.getSource() == b3) {
                if (Color.GREEN.equals(tmp)) {
                    label.setText("You WIN");
                } else {
                    label.setText("You Loose");
                }
            }
            updateUI(); //<---------------IMPORTANT To Sync What you see with each button press.
        }
    }
    

    【讨论】:

    • 我知道这段代码并不完美,我现在只是尝试学习这一点,但你的评论和观察也给了我很多帮助。我真的很感激!如果我可以再问你一个小问题……我如何在按下一个按钮后停止程序运行?如果可能的话...谢谢。
    【解决方案2】:

    我认为您只是弄乱了大括号(和缩进)。请在 IDE 中使用自动缩进或自动格式化工具,它会快速定位这些问题。

    @Override
    public void actionPerformed(ActionEvent e) {
        if (e.getSource() == b1) {
            if (Color.BLUE.equals(colors)) {
                label.setText("You WIN");
            }
    //  v Problem is this extra brace
        }else {
            label.setText("You LOSE");
        } 
    

    改成

    @Override
    public void actionPerformed(ActionEvent e) {
        if (e.getSource() == b1) {
            if (Color.BLUE.equals(colors)) {
                label.setText("You WIN");
            }
            else {
              label.setText("You LOSE");
            } 
        } else if( //...
    

    【讨论】:

    • 感谢您的提问。
    • 但是你还没有回答我的问题... :/
    【解决方案3】:

    您的颜色数组不应在 paintComponent() 方法中创建。它应声明为 PaintPanel 实例变量,并应在 PaintPanel 构造函数中创建。

    这是一种可能性(您不需要单独的类;我在 PaintPanel 中添加了一个主类):

    import java.awt.BorderLayout;
    import java.awt.Color;
    import java.awt.Dimension;
    import java.awt.Graphics;
    import java.awt.event.ActionEvent;
    import java.awt.event.ActionListener;
    import java.awt.event.WindowAdapter;
    import java.awt.event.WindowEvent;
    import java.util.Random;
    
    import javax.swing.JButton;
    import javax.swing.JFrame;
    import javax.swing.JLabel;
    import javax.swing.JPanel;
    import javax.swing.SwingUtilities;
    import javax.swing.WindowConstants;
    
    public class PaintPanel extends JPanel implements ActionListener {
    
       int             x        = 200, y = 250;
       private JButton b1       = new JButton("BLUE");
       private JButton b2       = new JButton("RED");
       private JButton b3       = new JButton("GREEN");
       JLabel          label    = new JLabel("Choose the right Color");
       JPanel          subPanel = new JPanel();
       private Color   circleColor;
    
       public PaintPanel() {
    
          setLayout(new BorderLayout());
          setPreferredSize(new Dimension(440, 440));
          add(label, BorderLayout.NORTH);
          b1.addActionListener(this);
          b2.addActionListener(this);
          b3.addActionListener(this);
          subPanel.add(b1);
          b1.setForeground(Color.BLUE);
          subPanel.add(b2);
          b2.setForeground(Color.RED);
          subPanel.add(b3);
          b3.setForeground(Color.GREEN);
          add(subPanel, BorderLayout.SOUTH);
    
          Random rand = new Random();
          int rc = rand.nextInt(3);
          switch (rc) {
          case 1:
             circleColor = Color.RED;
             break;
          case 2:
             circleColor = Color.GREEN;
             break;
          default:
             circleColor = Color.BLUE;
             break;
          }
    
       }
    
       @Override
       public void paintComponent(Graphics g) {
          super.paintComponent(g);
          g.setColor(circleColor);
          g.fillOval(x, y, 30, 30);
    
       }
    
       @Override
       public void actionPerformed(ActionEvent e) {
          JButton b = (JButton) e.getSource();
          if (b.getForeground().equals(circleColor)) {
             label.setText("You WIN");
          } else {
             label.setText("You LOSE");
          }
       }
    
       public static void main(String[] args) {
          SwingUtilities.invokeLater(new Runnable() {
             @Override
             public void run() {
                // create the main frame
                JFrame frame = new JFrame();
                // create the component to display in the frame
                PaintPanel comp = new PaintPanel();
                frame.add(comp, BorderLayout.CENTER);
    
                frame.pack();
                frame.setVisible(true);
                frame.setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE);
                frame.addWindowListener(new WindowAdapter() {
                   @Override
                   public void windowClosing(WindowEvent arg0) {
                      System.exit(0);
                   }
                });
             }
          });
    
       }
    }
    

    【讨论】:

    • 我是任何这些方面的初学者,但我很欣赏你的问题 - 如果我问你,你会尝试从代码中写给我这个小片段以及如何在 actionPerformed 方法中从构造函数调用吗?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-01-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多