简体   繁体   中英

Using a single EventHandler for entire array in Java

I've looked everywhere online and have been stumped for a few hours now. I have a program where I have an array of 40 imageViews on a screen. What I want to happen is when I click on a particular imageView in the array, I want the image to change within the imageView.

Here is what I have:

public void initBubbles(){
    Image image = new Image("file:src/bubbles/images/bubble.png");
    for (int i = 0; i < bubbles.length; i++) {
        //Creates a new bubble
        bubbles[i] = new Bubble(image, 'A', 1);

        //Creates a new image view
        ivs[i] = new ImageView(image);

       //Various lines of codes that put the imageView in the scene..... (Not relevant)


      ivs[i].addEventHandler(MouseEvent.MOUSE_CLICKED, new EventHandler<MouseEvent> () {

            @Override
            public void handle(MouseEvent event) {
                System.out.println("Bubble Popped!");
                ivs[i].setImage(new Image("popped.png":); //Will result in arrayOutOfBounds
            }
        });

    }

}

The problem I am running into is getting the selected element from the MouseEvent. I understand that the line right after the "Bubble Popped!" message will cause an ArrayOutOfBounds exception. But I hope you understand what I am trying to. How can I get the imageView that was clicked based on the MouseEvent?

Any help is greatly appreciated as I've been stuck for a few hours.

I cannot check it in compiler now but based on the documentation I guess you will refer to the correct ImageView by the getTarget() method which MouseEvent inherits from javafx.event.Event .

So the correct code would be something like this:

@Override
public void handle(MouseEvent event) {
    final ImageView iv = (ImageView) (event.getTarget());
    iv.setImage(new Image("popped.png"));
}

And if you really wish to have a single EventHandler for entire array, you should define it outside of the for loop and assign it to a variable - otherwise you are creating a new instance of the handler for each ImageView.

public void initBubbles(){
    final Image image = new Image("file:src/bubbles/images/bubble.png");
    // Create an event handler to be re-used for all the ImageView's
    final EventHandler eventHandler = new EventHandler<MouseEvent> () {
        @Override
        public void handle(MouseEvent event) {
            final ImageView iv = (ImageView) (event.getTarget());
            iv.setImage(new Image("popped.png"));
        }
    }
    for (int i = 0; i < bubbles.length; i++) {
        //Creates a new bubble
        bubbles[i] = new Bubble(image, 'A', 1);
        //Creates a new image view
        ivs[i] = new ImageView(image);
        // Register the event handler
        ivs[i].addEventHandler(MouseEvent.MOUSE_CLICKED, eventHandler);
    }
}

The handler code runs in different context than where you register the handler ( addEventHandler() ), so the value of i does not have the same meaning. You should consider the code of the handle() method as completely separate and independent on its surrounding code. The information of the "run-time context" of the handler is in the event which triggered the handler .

To use a parable, by calling the addEventHandler() you tell the ImageView this:

Dear ImageView, when a mouse event occurs above you, call the code of the handler.

And the handler:

Dear handler, when you are triggered, have a look at the target upon which you have been called, consider it as an instance of ImageView and set its image to something new.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM