How show specific part of an image in javafx

后端 未结 3 913
感动是毒
感动是毒 2020-11-30 15:25

\"my

i have this picture(all of these effects are in one .png file ) i want to display for example seco

相关标签:
3条回答
  • 2020-11-30 15:46

    As someone who is new to JavaFX, I had the same question. The question asks for much less than the above answers provide. We just want to manually select and display a portion of the image in an ImageView without animation. Here is the simplest solution wherein the user enters the image number and presses a button to display the desired image part.

    
    package com.pakzaban;
    
    import javafx.fxml.FXML;
    import javafx.geometry.Rectangle2D;
    import javafx.scene.control.TextField;
    import javafx.scene.image.Image;
    import javafx.scene.image.ImageView;
    
    public class Controller {
    
        @FXML
        public ImageView imageView;
        public TextField numberField;
        private final int IMAGE_WIDTH = 50;
        private final int IMAGE_HEIGHT = 80;
        private int imageNumber = 1;
    
        public void onSetImagePressed(){
            try {
                imageNumber = Integer.parseInt(numberField.getText());
    
                //SET THE WHOLE IMAGE INTO IMAGEVIEW
                Image wholeImage = new Image("com/pakzaban/wholePicture.png");
                imageView.setImage(wholeImage);
    
                //SET THE VIEWPORT TO DESIRED PART OF THE IMAGE
                Rectangle2D imagePart = new Rectangle2D((imageNumber - 1) * IMAGE_WIDTH, 0, IMAGE_WIDTH, IMAGE_HEIGHT);
                imageView.setViewport(imagePart);
            }
            catch (Exception e){
                e.printStackTrace();
            }
        }
    }
    

    0 讨论(0)
  • 2020-11-30 15:47

    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.

    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();
        }
    }
    
    0 讨论(0)
  • 2020-11-30 16:00

    You can utilize the clip property of the Node, along with x property of the ImageView. Below is a demo showing the part of image in timeline, like a gif animated picture:

    @Override
    public void start(Stage stage) {
    
        Group root = new Group();
        Image image = new Image(this.getClass().getResource("your.png").toExternalForm());
    
        final int numberOfFrames = 6; // in image
        double frameWidth = image.getWidth() / numberOfFrames;
        Scene scene = new Scene(root, frameWidth, image.getHeight());
        final ImageView view = new ImageView(image);
    
        Rectangle mask = new Rectangle(frameWidth, image.getHeight());
        view.setClip(mask);
    
        Timeline timeline = new Timeline();
    
        for (int i = 0; i <= numberOfFrames; i++) {
            KeyFrame kf = new KeyFrame(Duration.seconds(i), new KeyValue(view.xProperty(), -frameWidth * i, Interpolator.DISCRETE));
            timeline.getKeyFrames().add(kf);
        }
        timeline.setCycleCount(Timeline.INDEFINITE);
        timeline.play();
    
        root.getChildren().add(view);
        stage.setScene(scene);
        stage.show();
    
    }
    
    0 讨论(0)
提交回复
热议问题