1

Expectation

enter image description here

There is an ArrayList that has 3 Images. There are 3 ImageViews. There is a button. When the button is pressed, each ImageView is continuously updated with an Image from the ArrayList of Images. (continuously iterate in the ArrayList and update the view with the next image) Like a slot machine in a casino. When I press the button again. ImageViews should stop updating images.

My Code

package slotMachine;

import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.layout.HBox;
import javafx.stage.Stage;

import java.util.ArrayList;
import java.util.Collections;
import java.util.concurrent.TimeUnit;

public class TestClass extends Application{

    //3 ImageView
    static ImageView view1= new ImageView();
    static ImageView view2= new ImageView();
    static ImageView view3= new ImageView();

    //3 Images
    static Image image1 = new Image("file:resources/bell.png");
    static Image image2 = new Image("file:resources/cherry.png");
    static Image image3 = new Image("file:resources/lemon.png");

    static Button button = new Button("Press");

    //ArrayList holding the 3 images
    static ArrayList<Image> array = new ArrayList<Image>();


    static boolean spinning = false;



    @Override
    public void start(Stage primaryStage) throws Exception {
        //add images to the arrayList
        array.add(image1);
        array.add(image2);
        array.add(image3);

        HBox outerBox = new HBox();
        outerBox.getChildren().addAll(view1, view2, view3, button);

        button.setOnAction(event -> spin());


        Scene scene = new Scene(outerBox, 1000, 400);
        primaryStage.setScene(scene);
        primaryStage.show();
    }

    public static void spin(){

        if(spinning){
            spinning = false;
        }
        else {
            spinning = true;
        }

        //Create 3 threads to spin images in 3 different ImageViews
        SpinClass r1 = new SpinClass(array, view1);
        Thread t1 = new Thread(r1);
        t1.start();

        SpinClass r2 = new SpinClass(array, view2);
        Thread t2 = new Thread(r2);
        t2.start();

        SpinClass r3 = new SpinClass(array, view3);
        Thread t3 = new Thread(r3);
        t3.start();
    }

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

class SpinClass implements Runnable{
    ArrayList<Image> arr;
    ImageView view;

    public SpinClass(ArrayList<Image> arr, ImageView view) {
        this.arr = arr;
        this.view = view;
    }

    @Override
    public void run() {
        Collections.shuffle(arr); //shuffle images in array
        int position = 0;

        //spin images in current ImageView until button is pressed again.
        while (TestClass.spinning){
            view.setImage(arr.get(position));
            view.setPreserveRatio(true);
            view.setFitWidth(100);
            view.setFitHeight(100);
            position = (position + 1) % arr.size();

            try {
                TimeUnit.MILLISECONDS.sleep(50);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

        }
    }
}

Outcome

I don't get a consistent outcome.

Sometimes I only get one view that is updating the images.

enter image description here

Sometimes all 3 images are updating. Another time only two images are updating or all 3 starts to update but one or two stop without me pressing the button.

enter image description here

Also, I tried creating 3 different arraylists instead of all threads accessing the same ArrayList. But the problem persists.

array1.add(new Image("file:resources/bell.png"));
array1.add(new Image("file:resources/cherry.png"));
array1.add(new Image("file:resources/lemon.png"));

array2.add(new Image("file:resources/bell.png"));
array2.add(new Image("file:resources/cherry.png"));
array2.add(new Image("file:resources/lemon.png"));

array3.add(new Image("file:resources/bell.png"));
array3.add(new Image("file:resources/cherry.png"));
array3.add(new Image("file:resources/lemon.png"));
Arghavan
  • 1,125
  • 1
  • 11
  • 17
Enzio
  • 799
  • 13
  • 32
  • 2
    You're updating the UI from a background thread, which violates the thread of rules of JavaFX. Either wrap the individual UI updates in `Platform.runLater()`, or (better) use the animation API and don't use background threads at all. See https://stackoverflow.com/questions/9966136/javafx-periodic-background-task – James_D Nov 07 '17 at 10:30

0 Answers0