如何在javafx中显示图像的特定部分

我的形象

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

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

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

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

重打

更简单的例子

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

动画图像类似于Sprite 。 下面的代码并不是一个生产质量的Sprite系统(可能是一个真正的Sprite系统,用于游戏会有更多的function和特性),它只是演示了基于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(); } } 

您可以使用Node的clip属性以及ImageView x属性。 下面是一个演示时间轴中图像部分的演示,如gif动画图片:

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