In this shot, we will build a Java Swing application that draws die faces on the interface.
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);}}
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 JButton
s 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.
Die
classNow 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
.
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:
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);}}
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.
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); } }
Free Resources