如何在javafx中显示图像的特定部分 [英] How show specific part of an image in javafx

查看:69
本文介绍了如何在javafx中显示图像的特定部分的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述



我有这张照片(所有这些效果都在一个.png文件中)我想显示例如第二张图片如何在javafx中使用Image和ImageView来显示该图像的特定部分?谢谢

解决方案

这个答案是矫枉过正的。但是在你的问题中有一组漂亮的图像,也许是矫枉过正的要求: - )



基本设计和Uluk一样,它只是调整ImageView的视口而不是设置剪辑,但概念是相同的。



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;

类ExploadableImageView扩展了ImageView {
private final Rectangle2D [] cellClips;
private int numCells;
private final持续时间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);
时间轴kaboom =新时间轴(
新KeyFrame(FRAME_TIME,事件 - > {
frameCounter.set((frameCounter.get()+ 1)%numCells);
setViewport (cellClips [frameCounter.get()]);
})
);
kaboom.setCycleCount(numCells);
kaboom.setOnFinished(onFinished);
kaboom.play();
}
}

类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);
}
}

公共类CatWhack扩展Application {
public static void main(String [] args){
launch(args);
}

private static final int NUM_CELLS_PER_EXPLOSION = 6;

@Override
public void start(阶段阶段){
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
//看起来像imgur可能阻止从Java应用程序直接访问以下png(不知何故)。
//但您仍然可以从该位置下载QMqbQ.png
//并将其保存在与CatWhack程序相同的目录中
//然后通过替换新的来获取它图像调用:
//新图像(CatWhack.class.getResourceAsStream(QMqbQ.png));
图片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(猫捶 - 点击猫来打它!);
stage.setScene(new Scene(tiles));
stage.show();
}
}



更简单的例子



这是与上述游戏中演示的概念相同的概念,但只是使用更简单的动画图像系统,可以通过方法调用而不是用户鼠标点击图像来控制。



动画图像类似于

  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扩展了ImageView {
private final Rectangle2D [] cellClips;
private int numCells;
私人最终时间线时间表;
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();
}
}

公共类SpriteSample扩展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(阶段阶段){
//看起来像imgur可能阻止了从Java应用程序直接访问以下png(不知何故) )。
//但您仍然可以从该位置下载QMqbQ.png
//并将其保存在与CatWhack程序相同的目录中
//然后通过替换新的来获取它图像调用:
//新图像(Sprite.class.getResourceAsStream(QMqbQ.png));
图像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(新场景(布局));
stage.show();
}
}


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

解决方案

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();
    }
}

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();
    }
}

这篇关于如何在javafx中显示图像的特定部分的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆