如何通过ActionListener实现点击切换不重复的骰子图片?
问题描述
创建简易骰子GUI,要求点击按钮时显示随机骰子值图片,且不会连续出现相同值。目前已在ActionListener中编写代码,但点击后图片未切换。defineBtn方法中lblNewLabel.setIcon(dice[verifiedNum])本应实现图片切换,却出现编译错误:
Exception in thread "AWT-EventQueue-0" java.lang.Error: Unresolved compilation problem: lblNewLabel cannot be resolved
尝试将该行代码放入diceLbl方法中,图片仍无法切换,请问需要做哪些修改才能让JLabel随机切换图片且不重复?
原代码如下:
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; } }
解决方案
- 提升JLabel为类成员变量:原代码中
lblNewLabel是构造方法内的局部变量,defineBtn方法的ActionListener无法访问它。把lblNewLabel声明为类的成员变量,让ActionListener可以直接调用。 - 修正初始值匹配:初始化
lastRolledNum时,要和初始生成的骰子值保持一致,避免第一次点击时因为新随机数和初始值相同导致do-while死循环。 - 简化随机数生成逻辑:确保每次生成的随机数与上一次不同,逻辑保持简洁。
修改后的完整代码:
import java.awt.BorderLayout; import java.awt.Color; import java.awt.Component; import java.awt.Font; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.util.Random; import javax.swing.EmptyBorder; import javax.swing.ImageIcon; import javax.swing.JButton; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.SwingConstants; import javax.swing.SwingUtilities; 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(); // 提升为类成员变量 JLabel lblNewLabel; int lastRolledNum; /** * Launch the application. */ public static void main(String[] args) { SwingUtilities.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); 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) { int newRoll; do { newRoll = rand.nextInt(6); } while (newRoll == lastRolledNum); lastRolledNum = newRoll; lblNewLabel.setIcon(dice[lastRolledNum]); } }); return btnNewButton; } private JLabel diceLbl() { JLabel label = new JLabel(""); label.setOpaque(true); label.setBackground(new Color(192, 192, 192)); label.setHorizontalAlignment(SwingConstants.CENTER); // 初始化第一次的骰子值 lastRolledNum = rand.nextInt(6); label.setIcon(dice[lastRolledNum]); return label; } }
内容的提问来源于stack exchange,提问作者HalfokayCS
相关产品推荐
相关产品推荐

