Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
181 views
in Technique[技术] by (71.8m points)

java - How show specific part of an image in javafx

my image

i have this picture(all of these effects are in one .png file ) i want to display for example second picture how can i use Image and ImageView in javafx to display specific part of this image ? thanks

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

This answer is overkill. But with a nice set of images like you have in your question, maybe overkill is what is called for :-)

The fundamental design is the same as Uluk's, it just adjusts the Viewport of the ImageView rather than setting a clip, but the concept is the same.

Beware => Java 8

import javafx.animation.*;
import javafx.application.Application;
import javafx.beans.property.*;
import javafx.event.*;
import javafx.geometry.Rectangle2D;
import javafx.scene.Scene;
import javafx.scene.control.Control;
import javafx.scene.effect.*;
import javafx.scene.image.*;
import javafx.scene.layout.*;
import javafx.scene.paint.Color;
import javafx.stage.Stage;
import javafx.util.Duration;

class ExploadableImageView extends ImageView {
    private final Rectangle2D[] cellClips;
    private int numCells;
    private final Duration FRAME_TIME = Duration.seconds(.5);

    public ExploadableImageView(Image explosionImage, int numCells) {
        this.numCells = numCells;

        double cellWidth  = explosionImage.getWidth() / numCells;
        double cellHeight = explosionImage.getHeight();

        cellClips = new Rectangle2D[numCells];
        for (int i = 0; i < numCells; i++) {
            cellClips[i] = new Rectangle2D(
                    i * cellWidth, 0,
                    cellWidth, cellHeight
            );
        }

        setImage(explosionImage);
        setViewport(cellClips[0]);
    }

    public void explode(EventHandler<ActionEvent> onFinished) {
        final IntegerProperty frameCounter = new SimpleIntegerProperty(0);
        Timeline kaboom = new Timeline(
                new KeyFrame(FRAME_TIME, event -> {
                    frameCounter.set((frameCounter.get() + 1) % numCells);
                    setViewport(cellClips[frameCounter.get()]);
                })
        );
        kaboom.setCycleCount(numCells);
        kaboom.setOnFinished(onFinished);
        kaboom.play();
    }
}

class ExplodableItem extends StackPane {
    public ExplodableItem(Image objectImage, Image explosionImage, int numCells) {
        ImageView objectView = new ImageView(objectImage);
        ExploadableImageView explosionView = new ExploadableImageView(
                explosionImage, numCells
        );

        setMinSize(
                Math.max(
                        objectImage.getWidth(),
                        explosionView.getViewport().getWidth()
                ),
                Math.max(
                        objectImage.getHeight(),
                        explosionView.getViewport().getHeight()
                )
        );

        objectView.setPickOnBounds(false);
        objectView.setOnMouseClicked(event -> {
            getChildren().setAll(explosionView);
            explosionView.explode(complete -> getChildren().setAll(objectView));
        });

        DropShadow drop = new DropShadow(10, Color.GOLD);
        drop.setInput(new Glow());
        objectView.setOnMouseEntered(event -> objectView.setEffect(drop));
        objectView.setOnMouseExited(event -> objectView.setEffect(null));

        getChildren().setAll(objectView);
    }
}

public class CatWhack extends Application {
    public static void main(String[] args) {
        launch(args);
    }

    private static final int NUM_CELLS_PER_EXPLOSION = 6;

    @Override
    public void start(Stage stage) {
        Image objectImage    = new Image("http://icons.iconarchive.com/icons/iconka/meow/96/cat-box-icon.png");  // cat icon linkware: backlink to http://www.iconka.com required
        // looks likes imgur may have blocked direct access to following png from a Java app (somehow).
        // but you can still download the QMqbQ.png from that location 
        // and save it locally in the same directory as the CatWhack program
        // then pick it up by replacing the new Image call with:
        //    new Image(CatWhack.class.getResourceAsStream("QMqbQ.png")); 
        Image explosionImage = new Image("http://i.stack.imgur.com/QMqbQ.png");

        TilePane tiles = new TilePane();
        tiles.setPrefColumns(4);
        for (int i = 0; i <16; i++) {
            tiles.getChildren().add(
                    new ExplodableItem(objectImage, explosionImage, NUM_CELLS_PER_EXPLOSION)
            );
        }
        tiles.setMinSize(Control.USE_PREF_SIZE, Control.USE_PREF_SIZE);

        stage.setTitle("Cat Whack - Click a cat to whack it!");
        stage.setScene(new Scene(tiles));
        stage.show();
    }
}

whack

Simpler example

Here is the same concept as demonstrated in the above game, but just with a simpler system of an animated image which can be controlled via method calls rather than user mouse clicks on the image.

The animated image is similar to a Sprite. The code below is not meant to be a production quality Sprite system (probably a true Sprite system for a game would have more functions and features), it just demonstrates very simple display of an animated image based upon a Viewport.

simple image

import javafx.animation.*;
import javafx.application.Application;
import javafx.beans.property.*;
import javafx.geometry.*;
import javafx.scene.Scene;
import javafx.scene.control.ToggleButton;
import javafx.scene.image.*;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
import javafx.util.Duration;

class Sprite extends ImageView {
    private final Rectangle2D[] cellClips;
    private int numCells;
    private final Timeline timeline;
    private final IntegerProperty frameCounter = new SimpleIntegerProperty(0);

    public Sprite(Image animationImage, int numCells, Duration frameTime) {
        this.numCells = numCells;

        double cellWidth  = animationImage.getWidth() / numCells;
        double cellHeight = animationImage.getHeight();

        cellClips = new Rectangle2D[numCells];
        for (int i = 0; i < numCells; i++) {
            cellClips[i] = new Rectangle2D(
                    i * cellWidth, 0,
                    cellWidth, cellHeight
            );
        }

        setImage(animationImage);
        setViewport(cellClips[0]);

        timeline = new Timeline(
                new KeyFrame(frameTime, event -> {
                    frameCounter.set((frameCounter.get() + 1) % numCells);
                    setViewport(cellClips[frameCounter.get()]);
                })
        );
    }

    public void playOnce() {
        frameCounter.set(0);
        timeline.setCycleCount(numCells);
        timeline.stop();
        timeline.playFromStart();
    }

    public void playContinuously() {
        frameCounter.set(0);
        timeline.setCycleCount(Timeline.INDEFINITE);
        timeline.stop();
        timeline.playFromStart();
    }

    public void stop() {
        frameCounter.set(0);
        setViewport(cellClips[frameCounter.get()]);
        timeline.stop();
    }
}

public class SpriteSample extends Application {
    private static final int NUM_CELLS_PER_ANIMATION = 6;
    private static final Duration FRAME_TIME = Duration.seconds(.5);

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

    @Override
    public void start(Stage stage) {
        // looks likes imgur may have blocked direct access to following png from a Java app (somehow).
        // but you can still download the QMqbQ.png from that location 
        // and save it locally in the same directory as the CatWhack program
        // then pick it up by replacing the new Image call with:
        //    new Image(Sprite.class.getResourceAsStream("QMqbQ.png")); 
        Image tilesheetImage = new Image(SpriteSample.class.getResourceAsStream("QMqbQ.png"));
        Sprite sprite = new Sprite(tilesheetImage, NUM_CELLS_PER_ANIMATION, FRAME_TIME);

        ToggleButton animationControl = new ToggleButton("Animate");
        animationControl.setOnAction(event -> {
            if (animationControl.isSelected()) {
                animationControl.setText("Stop");
                sprite.playContinuously();
            } else {
                animationControl.setText("Animate");
                sprite.stop();
            }
        });

        VBox layout = new VBox(10, sprite, animationControl);
        layout.setPadding(new Insets(10));
        layout.setAlignment(Pos.CENTER);

        stage.setScene(new Scene(layout));
        stage.show();
    }
}

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...