如何在javafx中显示图像的特定部分 [英] How show specific part of an image in 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屋!