如何在KeyPressed

时间:2015-06-19 00:18:03

标签: javafx

我很难解决这个问题,我正在试图弄清楚当我按下键盘上的某个键时如何将ImageView更改为另一个ImageView,但我不知道怎么做,我已经几乎环顾四周在我能想到的任何地方,但是没有任何线索。

继承代码,这是一个字符类:

import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Files;
import java.nio.file.Paths;

import javafx.animation.Animation;
import javafx.application.Application;
import javafx.geometry.Rectangle2D;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.input.KeyCode;
import javafx.scene.paint.Color;
import javafx.stage.Stage;
import javafx.util.Duration;


public class Character extends Application{

private static final int COLUMNS  =  3;
private static final int COUNT    =  3;
private static final int WIDTH    = 48;
private static final int HEIGHT   = 50;
ImageView imgView;

public void start(Stage primaryStage) throws Exception {
    Group root = new Group();

    imgView = characterStill();
    root.setOnKeyPressed(e -> {
        if(e.getCode().equals(KeyCode.RIGHT)){
            try {
                imgView = characterWalking();
            } catch (IOException ex) {}
        }
    });
    root.setOnKeyReleased(e -> {
        if(e.getCode().equals(KeyCode.RIGHT)){
            try {
                imgView = characterStill();
            } catch (IOException ex) {}
        }
    });

    root.getChildren().add(imgView);
    Scene scene = new Scene(root, Menu.WIDTH, Menu.HEIGHT, Color.GREENYELLOW);
    primaryStage.setScene(scene);
    primaryStage.show();
}
public ImageView characterStill() throws IOException{
    InputStream is = Files.newInputStream(Paths.get("C:\\Users\\Javier\\Desktop\\StickHero\\StillNinja.png"));
    Image characterStill = new Image(is);
    ImageView stillView = new ImageView(characterStill);

    return stillView;
}
public ImageView characterWalking() throws IOException{
    final InputStream is = Files.newInputStream(Paths.get("C:\\Users\\Javier\\Desktop\\StickHero\\WalkingNinja.png"));
    final Image characterWalking = new Image(is);
    ImageView charView = new ImageView(characterWalking);

    charView.setViewport(new Rectangle2D(0, 0, WIDTH, HEIGHT));

    final Animation animation = new AnimationGen(charView, Duration.millis(300), COUNT, COLUMNS, 0, 0, WIDTH, HEIGHT);
    animation.setCycleCount(Animation.INDEFINITE);
    animation.play();

    return charView;
}
}

1 个答案:

答案 0 :(得分:2)

在Java中,所有对象都通过引用访问。保持内存中对象与对象引用之间的区别是很重要的。

执行时

new ImageView(characterStill);

在内存中创建一个新的ImageView对象。然后你(有效地)做

imgView = new ImageView(characterStill);

您将变量imgView 引用分配给该对象。您可以将引用视为对象的内存位置(尽管实际上它不一定必须以这种方式实现)。

初始化时代码中发生的情况实际上如下:

imgView = new ImageView(characterStill);
root.getChildren().add(imgView);

因此imgView包含对显示ImageView图像的characterStill对象的引用。然后,您将该引用传递给root的子列表,因此现在root的子列表包含对同一ImageView个对象的引用。

现在,当用户按下 RIGHT 键时,你 (有效地)执行

imgView = new ImageView(characterWalking);

这会在内存中创建一个新的ImageView对象,并将对它的引用(想想:这个新对象的内存位置)赋给变量imgView

但是,root的子列表没有更改:它仍包含对第一个ImageView对象的原始引用。因此,您的用户界面没有任何变化。

您可以通过将root的子列表替换为新创建的ImageView来解决此问题,即:

root.setOnKeyPressed(e -> {
    if(e.getCode().equals(KeyCode.RIGHT)){
        try {
            imgView = characterWalking();
            root.getChildren().setAll(imgView);
        } catch (IOException ex) {}
    }
});

然而,这不是很有效。在每次按键时,您都可以从硬盘驱动器中新装入的图像中在内存中创建一个全新的对象。然后丢弃前一个对象并将新对象放入UI中。

更好的方法是使用单个ImageView对象,并替换它显示的图像。你可以通过调用

来做到这一点
imgView.setImage(...);

为了提高效率,您不必每次都从磁盘加载图像,而只需在启动时加载图像,然后重复使用它们。此代码看起来像

import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Files;
import java.nio.file.Paths;

import javafx.animation.Animation;
import javafx.application.Application;
import javafx.geometry.Rectangle2D;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.input.KeyCode;
import javafx.scene.paint.Color;
import javafx.stage.Stage;
import javafx.util.Duration;


public class Character extends Application{

    private static final int COLUMNS  =  3;
    private static final int COUNT    =  3;
    private static final int WIDTH    = 48;
    private static final int HEIGHT   = 50;
    private ImageView imgView;
    private Image characterStill ;
    private Image characterWalking ;
    private Animation animation ;

    public void start(Stage primaryStage) throws Exception {

        imgView = new ImageView();
        characterStill = loadCharacterStill();
        characterWalking = loadCharacterWalking();
        imgView.setViewport(new Rectangle2D(0, 0, WIDTH, HEIGHT));

        animation = new AnimationGen(charView, Duration.millis(300), COUNT, COLUMNS, 0, 0, WIDTH, HEIGHT);
        animation.setCycleCount(Animation.INDEFINITE);

        imgView.setImage(characterStill);

        Group root = new Group();

        root.setOnKeyPressed(e -> {
            if(e.getCode().equals(KeyCode.RIGHT)){
                imgView.setImage(characterWalking);
                animation.play();
            }
        });
        root.setOnKeyReleased(e -> {
            if(e.getCode().equals(KeyCode.RIGHT)){
                imgView.setImage(characterStill);
                animation.stop();
            }
        });

        root.getChildren().add(imgView);
        Scene scene = new Scene(root, Menu.WIDTH, Menu.HEIGHT, Color.GREENYELLOW);
        primaryStage.setScene(scene);
        primaryStage.show();
    }

    public Image loadCharacterStill() throws IOException{
        InputStream is = Files.newInputStream(Paths.get("C:\\Users\\Javier\\Desktop\\StickHero\\StillNinja.png"));
        Image characterStill = new Image(is);
        return characterStill ;
    }

    public Image loadCharacterWalking() throws IOException{
        final InputStream is = Files.newInputStream(Paths.get("C:\\Users\\Javier\\Desktop\\StickHero\\WalkingNinja.png"));
        final Image characterWalking = new Image(is);
        return characterWalking ;
    }

}

显然,由于我无法访问您的图片或AnimationGen课程,我没有对此进行测试;它应该给你这个想法。