Come mostrare parte specifica di un’immagine in javafx

la mia immagine

ho questa immagine (tutti questi effetti sono in un file .png) voglio visualizzare ad esempio la seconda immagine come posso usare Image e ImageView in javafx per visualizzare una parte specifica di questa immagine? Grazie

Questa risposta è esagerata. Ma con una bella serie di immagini come quelle che hai nella tua domanda, forse l’eccessivo è ciò che è richiesto 🙂

Il design fondamentale è lo stesso di Uluk, si limita a regolare il Viewport di ImageView piuttosto che impostare una clip, ma il concetto è lo stesso.

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

picchiare

Esempio più semplice

Ecco lo stesso concetto dimostrato nel gioco sopra, ma solo con un sistema più semplice di un'immagine animata che può essere controllata tramite le chiamate al metodo anziché i clic del mouse dell'utente sull'immagine.

L'immagine animata è simile a una Sprite . Il codice seguente non è pensato per essere un sistema Sprite di qualità di produzione (probabilmente un vero sistema Sprite per un gioco avrebbe più funzioni e caratteristiche), ma solo una visualizzazione molto semplice di un'immagine animata basata su un Viewport.

immagine semplice

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

È ansible utilizzare la proprietà clip del Node , insieme alla proprietà x di ImageView . Di seguito è una demo che mostra la parte di immagine nella timeline, come una immagine animata 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(); }