Trusted answers to developer questions
Trusted Answers to Developer Questions

Related Tags

java

How to draw dots for 1, 2, 3, 4, 5, & 6 on dice using Java

Hammad Nasir

Overview

In this shot, we will build a Java Swing application that draws die faces on the interface.

Die face application

First, we will start off with a standard Java JFrame boilerplate code, as follows:

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class Main extends JFrame {
	public Main() {
		super("Die App");
		setSize(Toolkit.getDefaultToolkit().getScreenSize());
		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
	}
	public static void main(String[] args) {
		new Main().setVisible(true);
	}
}

Setting up the interface

Now, we will add six buttons on the interface by using the JButton class, which will be used to toggle the die faces:

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class Main extends JFrame {
	private JButton[] buttons;
	public Main() {
		super("Die App");
		initComponents();
		setSize(Toolkit.getDefaultToolkit().getScreenSize());
		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
	}
	private void initComponents() {
		buttons = new JButton[6];
		for (int i = 0; i < buttons.length; i++) {
			buttons[i] = new JButton(Integer.toString(i + 1));
		}
		setLayout(null);
		for (int i = 0; i < buttons.length; i++) {
			add(buttons[i]);
			buttons[i].setBounds((60 * i) + 5, 5, 50, 25);
		}
	}
	public static void main(String[] args) {
		new Main().setVisible(true);
	}
}

In the above code snippet, we add a private JButton array member in line 5 with the identifier buttons. The buttons array will hold the instances of JButton inside.

Next, we create a private void method, initComponents. In this method, we initialize our buttons and place them on our layout.

In lines 12 to 23, we first initialize the buttons array to be of size 6, and then loop over this array and initialize every element with a JButton instance. The code Integer.toString(i + 1) adds 1 to i's value and converts it to the string. The JButtons are initialized with this string value, which is displayed on the button.

The next loop, starting in line 18, adds the button onto the interface via the add method call and sets the positioning and dimension of the buttons using the setBounds method call.

The Die class

Boilerplate

Now that our basic interface is set up, we move on to the die interface. For the die, we will be using the JPanel class. The following is a standard boilerplate code:

import javax.swing.JPanel;
import java.awt.Color;

public class Die extends JPanel {
    private static final int WIDTH = 120;
    private static final int HEIGHT = 120;
    private int number;
    public Die() {
        this.setBounds(125, 40, WIDTH, HEIGHT);
        this.setBackground(Color.gray);
        number = 1;
    }
}

In the code above, we declare two static integer variables, WIDTH and HEIGHT. These variables store the width and height of the Die in pixels. The private integer number is a variable that will store which face the die is set to. The constructor of the Die class positions the JPanel, sets its color to gray, and initializes number to the value 1.

Painting the die

The JPanel represents the face of the die. We will draw black colored dots in the JPanel at various positions to denote different numbered die faces. For this, we will use the paintComponent method.

paintComponent is an overrideable method that is called whenever the program is instructed to paint the component on the screen; in our case, the JPanel. The paintComponent is passed a Graphics argument, which we can draw over the JPanel:

public void paintComponent(Graphics g) {
    // Clear JPanel
    g.setColor(Color.gray);
    g.fillRect(0, 0, WIDTH, HEIGHT);

// Draw dots - To do
}

In the above code, g.setColor sets the color of g to gray, and g.fillRect fills the whole JPanel with this color. This is equivalent to clearing the JPanel.

In order to draw dots, we will create an auxiliary function drawDot, as follows:

private void drawDot(Graphics g, int x, int y) {
    g.setColor(Color.black);
    g.fillOval(x - 10, y - 10, 20, 20);
}

The drawDot method will create a black circle with a diameter of 20 pixels at the position specified by the x and y arguments.

Since we have the drawDot method, we can use it inside the paintComponent method to draw dots. We will use a switch statement on the number variable to draw dots based on which face the die is set to. The following categorizes the various dot positions of every face:

  • Face 1:
    • Center Dot
  • Face 2:
    • Top Left Dot
    • Bottom Right Dot
  • Face 3:
    • Top Left Dot
    • Center Dot
    • Bottom Right Dot
  • Face 4:
    • Top Left Dot
    • Top Right Dot
    • Bottom Left Dot
    • Bottom Right Dot
  • Face 5:
    • Top Left Dot
    • Top Right Dot
    • Center Dot
    • Bottom Left Dot
    • Bottom Right Dot
  • Face 6:
    • Top Left Dot
    • Top Right Dot
    • Center Left Dot
    • Center Right Dot
    • Bottom Left Dot
    • Bottom Right Dot

The following table provides x and y coordinates in terms of WIDTH and HEIGHT of the Die class:

Dot x y
Top Left Dot WIDTH / 4 HEIGHT / 4
Top Right Dot 3 * WIDTH / 4 HEIGHT / 4
Center Left Dot WIDTH / 4 HEIGHT / 2
Center Dot WIDTH / 2 HEIGHT / 2
Center Right Dot 3 * WIDTH / 4 HEIGHT / 2
Bottom Left Dot WIDTH / 4 3 * HEIGHT / 4
Bottom Right Dot 3 * WIDTH / 4 3 * HEIGHT / 4

After completing the paintComponent method, we also need to provide a method to change the number variable’s value and then repaint the component. For this, we define the changeDieFace method as follows:

public void changeDieFace(int num) {
    number = num;
    repaint();
}

Now, we put all the pieces together and our Dice class is ready:

import javax.swing.JPanel;
import java.awt.Color;
import java.awt.Graphics;

public class Die extends JPanel {
    private static final int WIDTH = 120;
    private static final int HEIGHT = 120;
    private int number;
    public Die() {
        this.setBounds(125, 40, WIDTH, HEIGHT);
        this.setBackground(Color.gray);
        number = 1;
    }
    public void changeDieFace(int num) {
        number = num;
        repaint();
    }
    public void paintComponent(Graphics g) {
        g.setColor(Color.gray);
        g.fillRect(0, 0, WIDTH, HEIGHT);
        switch(number) {
            case 1:
                drawDot(g, WIDTH / 2, HEIGHT / 2);
                break;
            case 2:
                drawDot(g, WIDTH / 4, HEIGHT / 4);
                drawDot(g, 3 * WIDTH / 4, 3 * HEIGHT / 4);
                break;
            case 3:
                drawDot(g, WIDTH / 4, HEIGHT / 4);
                drawDot(g, WIDTH / 2, HEIGHT / 2);
                drawDot(g, 3 * WIDTH / 4, 3 * HEIGHT / 4);
                break;
            case 4:
                drawDot(g, 3 * WIDTH / 4, HEIGHT / 4);
                drawDot(g, WIDTH / 4, HEIGHT / 4);
                drawDot(g, 3 * WIDTH / 4, 3 * HEIGHT / 4);
                drawDot(g, WIDTH / 4, 3 * HEIGHT / 4);
                break;
            case 5:
                drawDot(g, 3 * WIDTH / 4, HEIGHT / 4);
                drawDot(g, WIDTH / 4, HEIGHT / 4);
                drawDot(g, WIDTH / 2, HEIGHT / 2);
                drawDot(g, 3 * WIDTH / 4, 3 * HEIGHT / 4);
                drawDot(g, WIDTH / 4, 3 * HEIGHT / 4);
                break;
            case 6:
                drawDot(g, 3 * WIDTH / 4, HEIGHT / 4);
                drawDot(g, WIDTH / 4, HEIGHT / 4);
                drawDot(g, WIDTH / 4, HEIGHT / 2);
                drawDot(g, 3 * WIDTH / 4, HEIGHT / 2);
                drawDot(g, 3 * WIDTH / 4, 3 * HEIGHT / 4);
                drawDot(g, WIDTH / 4, 3 * HEIGHT / 4);
                break;
        }
    }
    private void drawDot(Graphics g, int x, int y) {
        g.setColor(Color.black);
        g.fillOval(x - 10, y - 10, 20, 20);
    }
}

Connecting the pieces together

All that’s left is to place a Die instance in our Main class and cause the buttons on our Main class to change the die face.

First, we add a private Die member in the Main class with the identifier die. Next, we initialize this die variable inside the initComponents method and add it onto our interface. The Main class will now look as follows:

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class Main extends JFrame {
	private JButton[] buttons;
	private Die die;
	public Main() {
		super("Die App");
		initComponents();
		setSize(Toolkit.getDefaultToolkit().getScreenSize());
		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
	}
	private void initComponents() {
		die = new Die();
		buttons = new JButton[6];
		for (int i = 0; i < buttons.length; i++) {
			buttons[i] = new JButton(Integer.toString(i + 1));
		}
		setLayout(null);
		for (int i = 0; i < buttons.length; i++) {
			add(buttons[i]);
			buttons[i].setBounds((60 * i) + 5, 5, 50, 25);
		}
		add(die);
	}
	public static void main(String[] args) {
		new Main().setVisible(true);
	}
}

In order for our buttons to toggle the die faces, we need our Main class to implement the ActionListener interface. The ActionListener interface requires the actionPerformed method. We attach the actionPerformed method with all the buttons using the addActionListener method. So, whenever a button is pressed, our actionPerformed method will be invoked as follows:

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class Main extends JFrame implements ActionListener {
	private JButton[] buttons;
	private Die die;
	public Main() {
		super("Die App");
		initComponents();
		setSize(Toolkit.getDefaultToolkit().getScreenSize());
		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
	}
	private void initComponents() {
		die = new Die();
		buttons = new JButton[6];
		for (int i = 0; i < buttons.length; i++) {
			buttons[i] = new JButton(Integer.toString(i + 1));
		}
		setLayout(null);
		for (int i = 0; i < buttons.length; i++) {
			add(buttons[i]);
			buttons[i].addActionListener(this);
			buttons[i].setBounds((60 * i) + 5, 5, 50, 25);
		}
		add(die);
	}
	public void actionPerformed(ActionEvent e) {
		int num = Integer.parseInt(e.getActionCommand());
		die.changeDieFace(num);
	}
	public static void main(String[] args) {
		new Main().setVisible(true);
	}
}

In the code above, we attach the actionPerformed function with all the buttons in line 22. The actionPerformed function extracts the name of the button using the e.getActionCommand method, converts it into an integer using the Integer.parseInt method, and stores it inside the num integer variable. Afterward, the changeDieFace method is invoked on the die variable with the num as an argument.

Source code

The following is the complete source code for this application:

import javax.swing.JPanel;
import java.awt.Color;
import java.awt.Graphics;

public class Die extends JPanel {
    private static final int WIDTH = 120;
    private static final int HEIGHT = 120;
    private int number;
    public Die() {
        this.setBounds(125, 40, WIDTH, HEIGHT);
        this.setBackground(Color.gray);
        number = 1;
    }
    public void changeDieFace(int num) {
        number = num;
        repaint();
    }
    public void paintComponent(Graphics g) {
        g.setColor(Color.gray);
        g.fillRect(0, 0, WIDTH, HEIGHT);
        switch(number) {
            case 1:
                drawDot(g, WIDTH / 2, HEIGHT / 2);
                break;
            case 2:
                drawDot(g, WIDTH / 4, HEIGHT / 4);
                drawDot(g, 3 * WIDTH / 4, 3 * HEIGHT / 4);
                break;
            case 3:
                drawDot(g, WIDTH / 4, HEIGHT / 4);
                drawDot(g, WIDTH / 2, HEIGHT / 2);
                drawDot(g, 3 * WIDTH / 4, 3 * HEIGHT / 4);
                break;
            case 4:
                drawDot(g, 3 * WIDTH / 4, HEIGHT / 4);
                drawDot(g, WIDTH / 4, HEIGHT / 4);
                drawDot(g, 3 * WIDTH / 4, 3 * HEIGHT / 4);
                drawDot(g, WIDTH / 4, 3 * HEIGHT / 4);
                break;
            case 5:
                drawDot(g, 3 * WIDTH / 4, HEIGHT / 4);
                drawDot(g, WIDTH / 4, HEIGHT / 4);
                drawDot(g, WIDTH / 2, HEIGHT / 2);
                drawDot(g, 3 * WIDTH / 4, 3 * HEIGHT / 4);
                drawDot(g, WIDTH / 4, 3 * HEIGHT / 4);
                break;
            case 6:
                drawDot(g, 3 * WIDTH / 4, HEIGHT / 4);
                drawDot(g, WIDTH / 4, HEIGHT / 4);
                drawDot(g, WIDTH / 4, HEIGHT / 2);
                drawDot(g, 3 * WIDTH / 4, HEIGHT / 2);
                drawDot(g, 3 * WIDTH / 4, 3 * HEIGHT / 4);
                drawDot(g, WIDTH / 4, 3 * HEIGHT / 4);
                break;
        }
    }
    private void drawDot(Graphics g, int x, int y) {
        g.setColor(Color.black);
        g.fillOval(x - 10, y - 10, 20, 20);
    }
}

RELATED TAGS

java

CONTRIBUTOR

Hammad Nasir
Copyright ©2022 Educative, Inc. All rights reserved
RELATED COURSES

View all Courses

Keep Exploring