当前位置: 首页 > 知识库问答 >
问题:

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

洪浩
2023-03-14

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

共有3个答案

傅宏恺
2023-03-14

作为JavaFX的新手,我也有同样的问题。这个问题要求的比上面提供的答案要少得多。我们只想在ImageView中手动选择和显示图像的一部分,而无需动画。这是最简单的解决方案,其中用户输入图像编号并按下按钮以显示所需的图像部分。


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();
        }
    }
}
安轶
2023-03-14

您可以利用节点的clip属性,以及图像视图的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();

}
冯胤
2023-03-14

这个答案太过分了。但是,有了一组像你在问题中看到的那样好的图像,也许过度杀戮才是真正需要的:-)

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

当心=

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

更简单的示例

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

动画图像类似于精灵。下面的代码并不意味着是一个生产质量的精灵系统(可能一个真正的游戏精灵系统会有更多的功能和特点),它只是演示了基于视口的动画图像的非常简单的显示。

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();
    }
}
 类似资料:
  • 我正在用Java和JAVAFX开发一个国际象棋游戏。我的棋盘是一个JAVAFX组,包含一个正方形数组。我的正方形继承自JAVAFX rectangle类。我想在这些方块里面画一个图像(棋子的图像),但是我似乎找不到方法。当我使用setfill来绘制图案时,正方形的颜色消失了,这不是我想要的,我希望图像是透明的,并绘制在每个正方形的顶部。有什么想法吗?

  • 我想在JavaFX的ImageView中显示图像。图像应该从SQLite数据库中获取,并在场景加载时显示。我使用以下代码片段从数据库获取代码,并在之前创建的ImageView中显示它。但是图像没有按预期显示。我做错了吗?P. S.我测试了改变路径在两个和当读取文件从目录到。但似乎没有什么奏效。但是当我手动将一个图像文件放在src目录中并尝试读取它时,它就像一个魅力。但是我想展示一张从数据库中提取的

  • 它应该显示一个与掷骰子一致的图像,但什么也没有发生。有问题的图像在包中(如果有关系,请单击并拖入项目窗口)。我在system.out.print中添加了t,以便显示Dice1和2的结果,这样我就知道这是有效的。 我还需要添加一些东西来使它看起来像吗?我以前从未在JavaFX中使用过实际的图像....总的来说,我对JavaFX是新手。 GetChildren c:\users\ethan c.b的错

  • 问题内容: 假设我想要一种只显示HTML中250x250像素的图像的中心50x50像素的方法。我怎样才能做到这一点。另外,有没有办法对css:url()引用执行此操作? 我知道CSS中的 clip ,但这似乎仅在与绝对定位一起使用时才起作用。 问题答案: 一种方法是在容器(td,div,span等)中将要显示的图像设置为背景,然后调整背景位置以获取所需的精灵。

  • 我一直试图使用FXML在JavaFX应用程序中显示我的图像,但没有成功。我的代码: 没有错误,但我的图像没有显示。我想图像已加载,但未显示。 这可能吗?我怎么查?如果是的话,不应该有一个错误给它吗? 事实上,即使我给出了一个不正确的名称,也没有运行时错误。也许没上子弹? 我也试过加载不同的图像和改变尺寸,没有任何效果。 ->运行时错误#1 ->林特错误+运行时错误#1 ->林特错误+运行时错误#1

  • 问题内容: 我有一个图像,我想在applet中显示它,问题是图像无法显示。我的代码有问题吗? 谢谢… 这是我的代码: 问题答案: 我怀疑您做错了,这应该很简单: HTML / applet元素的内容是什么?图片的名称是什么?图像与HTML位于同一目录中吗? 更新1 代码的第二行(已更改)将尝试将文件加载到与HTML相同的目录中。 当然,您可能需要添加一个来跟踪图像的加载,因为该方法立即返回(现在)