如何在Java中使用JButton重新绘制组件?

时间:2012-10-28 14:14:13

标签: java swing components jbutton repaint

我正在尝试用Java编写一个名为HighLow的简单GUI骰子游戏。基本上,用户从50英镑的初始余额开始,他们可以选择三种不同的投注金额,如果他们选择低,则骰子必须落在2,3,4,5或6上,并支付1:1,如果他们选择高,骰子必须降落在8,9,10,11或12,并支付1:1。如果他们选择Sevens,骰子必须降落七,并支付4:1。有两个骰子,所以应该添加两者的价值。这不是我的问题,只是想我已经清楚了,所以你理解游戏的重点。

我对面板,事件处理以及类似的东西都是全新的,所以我目前正在学习但是我在努力解决这个问题时遇到了一些困难。我有五个类:Dice.java由getFaceValue()和throwDie()方法组成,用于模拟骰子的随机抛出。 DiceFace.java创建具有点/点的骰子。 DiceFaceViewer.java是框架类。 DiceFaceComponent是两个骰子的组件,GamePanel是所有JButtons和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;
    }
}

DiceFace

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);
    }
}

DiceFaceComponent

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();
    }
}

的GamePanel

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 个答案:

答案 0 :(得分:1)

不要在任何paint方法中调用重绘。这将导致重绘管理器安排另一个重绘事件,最终消耗CPU并停止编程。

而是为正在更新潜水面值的动作监听器调用repaint

骰子与骰子DiceFaceComponent之间也没有联系,它永远不会知道它应该绘制什么值。

另外,在你的DiceFace课程中,我不会在每次抽奖中重新创建“点”,这只是浪费。而是在构造函数中创建它们。

同样适用于paintComponent方法,不需要重新创建DiceFace,只需在构造类时创建两个引用并根据需要更新它们的面值。

我会使用Dice作为将所有各种元素联系在一起的基本模型。通过使用ChangeListerner之类的内容,Dice可以通知各个组件发生了更改,允许他们更新屏幕