me@michellealzoladesign.com

Mon - Fri: 8AM - 5PM MDT

Introduction

The Dice Simulator2 program is a simple JavaFX application that simulates rolling two dice. When the “Roll” button is clicked, the program generates two random numbers between 0 and 5 (inclusive), representing the value rolled on each die. The program then displays the corresponding dice images for each value using JavaFX’s ImageView class.

Now let’s take a closer look at the code. The program is written in Java and uses JavaFX library for GUI. The class DiceSimulator2 extends Application class which is part of JavaFX library. This class provides the entry point for JavaFX application. The main() method simply calls the launch() method which starts the JavaFX application.

public static void main(String[] args)
{
	launch(args);
}

The start() method is overridden from the Application class and contains the main code for the program. In this method, the GUI elements are created and added to the Scene object. Then the Scene object is set to the Stage object which represents the main window of the application. Finally, the Stage object is shown using the show() method.

@Override
public void start(Stage primaryStage)
{
         // statments....
}

The GUI elements of the program consist of a button, two ImageView objects to display the dice images and two methods to handle the button click event and the dice rolling logic.

rolledImageView1.setImage(rolledImage1);
rolledImageView2.setImage(rolledImage2);

The Button object is created with the label “Roll” and an event handler is set using a lambda expression. The event handler contains the code to roll the dice and display the corresponding images. The dice values are generated using a Random object which generates a random integer between 0 and 5. The tossedImage() method is called to get the file name of the image corresponding to the dice value.

roll.setOnAction(event ->
{
	Random rand = new Random();
			
	int value1 = rand.nextInt(6);
			
	String image1 = tossedImage(value1); .......
}

The tossedImage() method takes an integer argument that represents the value of the dice and returns the image file name.

The image files are loaded using the Image class and displayed using the ImageView class. The setImage() method is used to set the image and the setFitHeight() and setPreserveRatio() methods are used to adjust the image size and aspect ratio. Two ImageView objects are created to display the dice images side by side in a horizontal box layout.

rolledImageView1.setImage(rolledImage1);
rolledImageView1.setFitHeight(200);
rolledImageView1.setPreserveRatio(true);

The HBox and VBox classes are used to arrange the GUI elements in a horizontal and vertical layout respectively. The HBox object contains the two ImageView objects and the VBox object contains the button and the HBox object. The setPadding() method is used to add some padding to the VBox object.

HBox rolledImages = new HBox(20, rolledImageView1, rolledImageView2);
rolledImages.setAlignment(Pos.CENTER);
		
VBox allElements = new VBox(20, roll, rolledImages);
allElements.setAlignment(Pos.TOP_CENTER);
allElements.setPadding(new Insets(10));

Finally, a Scene object is created with the VBox object and dimensions of 600 by 300 pixels. The Scene object is set to the Stage object and the setTitle() method is used to set the title of the main window.

Scene scene = new Scene(allElements, 600, 300);		
primaryStage.setScene(scene);		
primaryStage.setTitle("Dice Simulator2");		
primaryStage.show();

See my Code

Java_Projects_Practice/DiceSimulator2.java at main · michellealzola/Java_Projects_Practice (github.com)

See the App in Action

Challenges

One of the challenges faced when developing a dice-rolling simulator using JavaFX is handling image file paths. In order to display images in a JavaFX application, the image files must be located in the correct directory and the file path must be specified correctly.

One potential issue is that the file path may be different on different machines. For example, if the image files are stored in a folder on the developer’s machine, the file path may be different when the application is run on a different machine. This can cause the application to fail to load the images, resulting in errors or blank images being displayed.

To overcome this challenge, one solution is to store the image files in a relative directory within the project folder. This allows the file path to be specified relative to the project folder, rather than an absolute file path that may be different on different machines.

Below are some solutions for handling image file paths:

String basePath = new File("").getAbsolutePath();
String imagePath = "/src/images/dice1.png";
String absolutePath = basePath.concat(imagePath);

This code first obtains the absolute path to the current working directory using new File("").getAbsolutePath(). It then specifies the relative path to the image file dice1.png using /src/images/dice1.png. Finally, it concatenates the two paths using basePath.concat(imagePath) to obtain the absolute path to the image file.

While this approach may work in some cases, it is not always reliable. The absolute path to the current working directory may differ between operating systems or when the code is executed from different locations. Additionally, hard-coding paths may make the code less portable and more prone to breaking if the file structure is changed.

A better approach is to use relative paths that are relative to the location of the Java class file itself. For example, if the DiceSimulator class file is located in the javafx_projects package and the image files are in a directory named images that is located in the same directory as the javafx_projects package, the following code can be used to obtain the path to the image files:

String imagePath = "images/dice1.png";
URL imageURL = getClass().getResource(imagePath);

This code uses the getClass() method to obtain a Class object that represents the DiceSimulator class, and then uses the getResource() method to obtain a URL to the dice1.png file that is located in the images directory relative to the location of the DiceSimulator class file. The getResource() method returns a null value if the file is not found, so it is important to check for this and handle the error appropriately.

By using relative paths that are relative to the location of the Java class file, the code becomes more portable and less prone to breaking if the file structure is changed.

I made a different approach to handling image file paths.

String image1 = tossedImage(value1);			
			
try {
    rolledImage1 = new Image(new File(image1).toURI().toURL().toExternalForm());
} catch (MalformedURLException e) {
    e.printStackTrace();
}

rolledImageView1.setImage(rolledImage1);
rolledImageView1.setFitHeight(200);
rolledImageView1.setPreserveRatio(true);

In this code, image1 is a string variable that stores the file path of the image. The File class is used to create a file object from the file path. The toURI() method is called on this file object to get the URI (Uniform Resource Identifier) of the file, which is then converted to a URL (Uniform Resource Locator) using the toURL() method. Finally, the toExternalForm() method is called on the URL to get a string representation of the URL, which is then passed to the Image constructor to create an image object.

This approach works fine for small applications with only a few image files, but it can become cumbersome for larger applications with many image files. A better approach is to use a resource bundle to manage the image files. This involves storing the image files in a separate folder in the project directory and using the getResource() method of the Class object to access the image files. This approach ensures that the image files are always accessible, regardless of the location of the project directory.

Conclusion

Developing a dice simulator application using JavaFX is an excellent way to learn the basics of GUI programming. We have discussed various aspects of building such an application, including designing the user interface, handling user events, and loading and displaying images. Along the way, we have encountered several challenges, such as correctly setting up the image file paths, which require careful attention to detail. However, by following the best practices outlined in this article and being patient, anyone can develop an effective and engaging dice simulator application. With more practice and experience, developers can create even more complex and versatile applications using JavaFX.

Reference

T. Gaddis and G. Muganda, Starting Out with Java – From Control Structures through Data Structures, 4th Edition, 330 Hudson Street, NY NY 10013: Pearson, 2019.

Recommended Articles