How can I change an image label upon click using actionListener

58 views Asked by At

I am trying to create a simple dice GUI where a random image of a dice value will appear on click, without the same value appearing twice in a row. I am to the point where I need to define the code in the actionListener, but upon clicking, the images do not change. The line of code that should cause the images to change is lblNewLabel.setIcon(dice[verifiedNum]) in the defineBtn method but I get the error that it cannot be resolved to a type. My question is: what changes do I need to make in order to get the JLabel to change images randomly without repeating the same image? The error I get is Exception in thread "AWT-EventQueue-0" java.lang.Error: Unresolved compilation problem: lblNewLabel cannot be resolved.


public class LabGuiDice extends JFrame {
    
    final ImageIcon image1 = new ImageIcon(LabGuiDice.class.getResource("/guiDice/img/die-1.png"));

    final ImageIcon image2 = new ImageIcon(LabGuiDice.class.getResource("/guiDice/img/die-2.png"));

    final ImageIcon image3 = new ImageIcon(LabGuiDice.class.getResource("/guiDice/img/die-3.png"));

    final ImageIcon image4 = new ImageIcon(LabGuiDice.class.getResource("/guiDice/img/die-4.png"));

    final ImageIcon image5 = new ImageIcon(LabGuiDice.class.getResource("/guiDice/img/die-5.png"));

    final ImageIcon image6 = new ImageIcon(LabGuiDice.class.getResource("/guiDice/img/die-6.png"));

    final JPanel contentPane;

    final ImageIcon[] dice = { image1, image2, image3, image4, image5, image6 };

    

    final Random rand = new Random();

    int randNum = rand.nextInt(6);

    int verifiedNum = 0;

    

    /**
     * Launch the application.
     */
    public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {
            public void run() {
                try {
                    LabGuiDice frame = new LabGuiDice();
                    frame.setVisible(true);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });
        
    }
        
    /**
     * Create the frame.
     */
    public LabGuiDice() {
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setBounds(100, 100, 450, 300);
        contentPane = new JPanel();
        contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));

        setContentPane(contentPane);
        contentPane.setLayout(new BorderLayout(0, 0));
        
        JButton btnNewButton = defineBtn();
        contentPane.add(btnNewButton, BorderLayout.SOUTH);
        
        JLabel lblNewLabel = diceLbl();
        contentPane.add(lblNewLabel, BorderLayout.CENTER);
        
        
        
    }
    
    private JButton defineBtn() {
        JButton btnNewButton = new JButton("Roll 'Em");
        btnNewButton.setAlignmentX(Component.CENTER_ALIGNMENT);
        btnNewButton.setAlignmentY(Component.TOP_ALIGNMENT);
        btnNewButton.setFont(new Font("Javanese Text", Font.PLAIN, 15));
        btnNewButton.setBackground(new Color(178, 172, 136));
        btnNewButton.setForeground(new Color(255, 255, 255));
        btnNewButton.addActionListener(new ActionListener() {public void actionPerformed(ActionEvent e) { 
            do{randNum = rand.nextInt(6);} 
            while (randNum == verifiedNum);
            verifiedNum = randNum;
            lblNewLabel.setIcon(dice[verifiedNum]);
            
            }});
        return btnNewButton;
    }

    

    private JLabel diceLbl() {
        JLabel lblNewLabel = new JLabel("");
        lblNewLabel.setOpaque(true);
        lblNewLabel.setBackground(new Color(192, 192, 192));
        lblNewLabel.setHorizontalAlignment(SwingConstants.CENTER);
        lblNewLabel.setIcon(dice[randNum]);
        lblNewLabel.setHorizontalAlignment(SwingConstants.CENTER);
        
        return lblNewLabel;
    }

    
}


When I tried to place lblNewLabel.setIcon(dice[verifiedNum]) inside of the diceLbl method the image still does not change upon click.

1

There are 1 answers

0
MadProgrammer On BEST ANSWER

You have...

private JLabel diceLbl() {
    JLabel lblNewLabel = new JLabel("");
    lblNewLabel.setOpaque(true);
    lblNewLabel.setBackground(new Color(192, 192, 192));
    lblNewLabel.setHorizontalAlignment(SwingConstants.CENTER);
    lblNewLabel.setIcon(dice[randNum]);
    lblNewLabel.setHorizontalAlignment(SwingConstants.CENTER);
    
    return lblNewLabel;
}

which is interesting, but each time it's called, it will create a new instance of JLabel.

Then in the constructor, you have...

JLabel lblNewLabel = diceLbl();
contentPane.add(lblNewLabel, BorderLayout.CENTER);

which defines a local variable lblNewLabel which adds (the newly created instance) to the frame.

But, lblNewLabel is undefined within the context of your ActionListener.

Start by creating a instance variable (below the definition of verifiedNum)

private JLabel lblNewLabel;

Then modify the diceLbl method to only every create a single instance of the JLabel, something like...

    private JLabel diceLbl() {
        if (lblNewLabel == null) {
            lblNewLabel = new JLabel("");
            lblNewLabel.setOpaque(true);
            lblNewLabel.setBackground(new Color(192, 192, 192));
            lblNewLabel.setHorizontalAlignment(SwingConstants.CENTER);
            lblNewLabel.setIcon(dice[randNum]);
            lblNewLabel.setHorizontalAlignment(SwingConstants.CENTER);
        }
        return lblNewLabel;
    }

Then, in your ActionListener you can simply do...

diceLbl().setIcon(dice[verifiedNum]);