如何在 Java 中使用 JButton 重绘组件?
Posted
技术标签:
【中文标题】如何在 Java 中使用 JButton 重绘组件?【英文标题】:How do I repaint a component by using a JButton in Java? 【发布时间】:2012-10-18 01:17:01 【问题描述】:我正在尝试用 Java 编写一个名为 HighLow 的简单 GUI 骰子游戏。基本上,用户以 50 英镑的初始余额开始,他们可以选择三种不同的投注金额,如果他们选择低,骰子必须落在 2、3、4、5 或 6 上并支付 1:1,如果他们选择高,骰子必须落在 8、9、10、11 或 12 上,赔率为 1:1。如果他们选择 7,骰子必须落在 7 上,赔率为 4:1。有两个骰子,所以两者的值都应该相加。这不是我的问题的重点,只是想我会澄清这一点,以便您了解游戏的重点。
我对面板、事件处理和类似的东西完全陌生,所以我目前正在学习,但我在尝试解决这个问题时遇到了一些困难。我有五个类: Dice.java 包含一个 getFaceValue() 和 throwDie() 方法来模拟骰子的随机投掷。 DiceFace.java 创建带有点/点的骰子。 DiceFaceViewer.java 是框架类。 DiceFaceComponent 是两个骰子的组件,GamePanel 是所有 JButton 和 JComboBox 等所在的面板。
这就是我到目前为止所做的:创建一个框架,将带有按钮等的面板粘贴进去,然后将骰子图像添加到框架中。我想要的是每当我单击“投掷骰子”按钮时,骰子就会被重新绘制到带有随机面的框架上。如果我打开和关闭窗口,它现在所做的就是生成一张随机的脸。
骰子
import java.util.Random;
public class Dice
// Instance variables
private int faceValue;
private int sides;
private Random generator;
public Dice(int s)
generator = new Random();
sides = s;
faceValue = generator.nextInt(sides) + 1;
// Simulates the throw of a die landing on a random face.
public int throwDie()
return faceValue = (int)(Math.random() * sides) + 1;
// Returns the current face value of the die
public int getFaceValue()
return faceValue;
// Set face value of die
public void setValue(int v)
faceValue = v;
骰子脸
import java.awt.*;
import java.awt.geom.*;
public class DiceFace
// Holds the seven possible dot positions on a standard die
private Ellipse2D.Double[] dots = new Ellipse2D.Double[7];
private Rectangle box;
private int xLeft;
private int yTop;
private int side;
private int diceValue;
public DiceFace(int s, int x, int y, int v)
side = s; // Dimension of dice face
xLeft = x; // xPos
yTop = y; // yPos
diceValue = v; // Pip value
public void draw(Graphics2D g2)
box = new Rectangle(xLeft, yTop, side, side);
makeDots();
// Black background
g2.setColor(Color.BLACK);
g2.fill(box);
// White dots on black
g2.setColor(Color.WHITE);
// Draw dots
if (diceValue == 1)
g2.fill(dots[0]);
else if (diceValue == 2)
g2.fill(dots[1]); g2.fill(dots[2]);
else if (diceValue == 3)
g2.fill(dots[0]); g2.fill(dots[1]); g2.fill(dots[2]);
else if (diceValue == 4)
g2.fill(dots[1]); g2.fill(dots[2]);
g2.fill(dots[3]); g2.fill(dots[4]);
else if (diceValue == 5)
g2.fill(dots[0]); g2.fill(dots[1]);
g2.fill(dots[2]); g2.fill(dots[3]); g2.fill(dots[4]);
else if (diceValue == 6)
g2.fill(dots[1]); g2.fill(dots[2]); g2.fill(dots[3]);
g2.fill(dots[4]); g2.fill(dots[5]); g2.fill(dots[6]);
public void makeDots()
int w = side/6; // Dot width
int h = side/6; // Dot height
dots[0] = new Ellipse2D.Double(xLeft + (2.5 * side)/6,
yTop + (2.5 * side)/6, h, w);
dots[1] = new Ellipse2D.Double(xLeft + (3.75 * side)/6,
yTop + (3.75 * side)/6, h, w);
dots[2] = new Ellipse2D.Double(xLeft + (1.25 * side)/6,
yTop + (1.25 * side)/6, h, w);
dots[3] = new Ellipse2D.Double(xLeft + (1.25 * side)/6,
yTop + (3.75 * side)/6, h, w);
dots[4] = new Ellipse2D.Double(xLeft + (3.75 * side)/6,
yTop + (1.25 * side)/6, h, w);
dots[5] = new Ellipse2D.Double(xLeft + (1.25 * side)/6,
yTop + (2.5 * side)/6, h, w);
dots[6] = new Ellipse2D.Double(xLeft + (3.75 * side)/6,
yTop + (2.5 * side)/6, h, w);
DiceFaceViewer
import java.awt.*;
import javax.swing.*;
public class DiceFaceViewer
public static void main(String[] args)
// Create frame
JFrame frame = new JFrame();
// Set frame attributes
frame.getContentPane().setPreferredSize(new Dimension(360, 320));
frame.pack();
frame.setTitle("High Low");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setResizable(false);
// Set location of frame to centre screen
Dimension dim = Toolkit.getDefaultToolkit().getScreenSize();
int w = frame.getSize().width;
int h = frame.getSize().height;
int x = (dim.width-w)/2;
int y = (dim.height-h)/2;
frame.setLocation(x, y);
DiceFaceComponent component = new DiceFaceComponent();
frame.add(component);
// Add panel to frame
GamePanel panel = new GamePanel();
frame.add(panel, BorderLayout.NORTH);
frame.setVisible(true);
骰子面组件
import java.awt.*;
import javax.swing.*;
public class DiceFaceComponent extends JComponent
// Instance variables
private int faceValue1;
private int faceValue2;
public DiceFaceComponent()
faceValue1 = new Dice(6).getFaceValue();
faceValue2 = new Dice(6).getFaceValue();
public void paintComponent(Graphics g)
super.paintComponent(g);
// Recover Graphics2D
Graphics2D g2 = (Graphics2D) g;
DiceFace dice1 = new DiceFace(75, 66, 160, faceValue1); // s, x, y, v
dice1.draw(g2);
repaint();
DiceFace dice2 = new DiceFace(75, 219, 160, faceValue2);
dice2.draw(g2);
repaint();
游戏面板
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class GamePanel extends JPanel
private int balance = 50;
public GamePanel()
// Components
JRadioButton highButton = new JRadioButton("High");
JRadioButton lowButton = new JRadioButton("Low");
JRadioButton sevensButton = new JRadioButton("Sevens");
// Button group
ButtonGroup bg = new ButtonGroup();
bg.add(highButton);
bg.add(lowButton);
bg.add(sevensButton);
add(highButton);
add(lowButton);
add(sevensButton);
// Array to hold bet amounts
String betAmounts[] = "£10", "£5", "£1";
// Bets combo box
JComboBox bets = new JComboBox(betAmounts);
add(bets);
// Balance
JLabel bal = new JLabel(" Balance: £" + balance);
add(bal);
// Throw dice button
final JButton throwButton = new JButton("Throw Dice");
add(throwButton, FlowLayout.RIGHT);
class Action implements ActionListener
Dice dice = new Dice(6);
public void actionPerformed(ActionEvent e)
dice.throwDie();
dice.getFaceValue();
throwButton.addActionListener(new Action());
【问题讨论】:
【参考方案1】:不要在任何paint
方法中调用repaint。这将导致重绘管理器安排另一个重绘事件,最终消耗您的 CPU 并停止您的编程。
改为调用 repaint
来获取更新潜水面值的动作侦听器。
骰子和骰子DiceFaceComponent
之间也没有任何联系,它永远不会知道它应该绘制什么值。
另外,在您的DiceFace
课程中,我不会费心在每次抽奖时重新创建“点”,这只是一种浪费。而是在构造函数中创建它们。
paintComponent
方法也是如此,不必费心重新创建 DiceFace,只需在构造类时创建两个引用并根据需要更新它们的面值。
我会使用Dice
作为将所有不同元素联系在一起的基本模型。通过使用ChangeListerner
之类的东西,Dice
可以通知各种组件发生了变化,允许它们更新屏幕
【讨论】:
以上是关于如何在 Java 中使用 JButton 重绘组件?的主要内容,如果未能解决你的问题,请参考以下文章