JavaFX 更改 imageView 中的图像
JavaFX change the image in an imageView
基本上我有一种方法可以将图像从数据库加载到 imageView 中,还有第二种方法可以更改图像我很成功 运行 这两种方法都没有出现异常,但是在 changeImage() 中的 setImage 之后方法我需要更新什么以及(场景,舞台)怎么可能。我知道在 javafx 的 swing 中没有像 repaint() 这样的方法,那么我该如何处理呢?
public class MainMenuController implements Initializable {
/**
* Initializes the controller class.
*/
@Override
public void initialize(URL url, ResourceBundle rb) {
// TODO
}
private AnchorPane stck1;
@FXML
private AnchorPane openSecondWindow(ActionEvent event) throws Exception {
GUIController ctrl = new GUIController();
Stage stage = new Stage();
setStck1((AnchorPane) FXMLLoader.load(InteractiveFictionGame2.class.getResource("GUI.fxml")));
ImageView img_1 = new ImageView(ctrl.loadImg().getImage());
img_1.setPreserveRatio(true);
img_1.setSmooth(true);
img_1.setCache(true);
getStck1().getChildren().add(img_1);
Scene scene = new Scene(getStck1());
stage.setTitle("Interactive Fiction Game");
stage.setScene(scene);
stage.setFullScreen(true);
// stage.sizeToScene();
stage.show();
return getStck1();
}
public class GUIController implements Initializable {
@FXML
private TabPane tb1;
/**
* Initializes the controller class.
*
* @param url
*/
@Override
public void initialize(URL url, ResourceBundle rb) {
// TODO
}
@FXML
private ImageView img_1;
public ImageView loadImg() {
try {
con = DriverManager.getConnection(host, unm, pswrd);
stmnt = con.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_READ_ONLY);
rs = stmnt.executeQuery(SQL);
rs.next();
fis = rs.getBinaryStream(4);
imgt = javax.imageio.ImageIO.read(fis);
Image newImg = SwingFXUtils.toFXImage(imgt, null);
img_1 = new ImageView();
img_1.setImage(newImg);
rs.close();
stmnt.close();
con.close();
} catch (Exception e) {
System.out.println("Not working");
}
return img_1;
}
public void changeImage() {
..
fis = rs.getBinaryStream(1);
imgt = javax.imageio.ImageIO.read(fis);
Image newImg = SwingFXUtils.toFXImage(imgt, null);
img_1.setImage(newImg);
...
} catch (Exception e) {
System.out.println("Not working");
}
return img_1;
}
您的问题
如果您的控制器中有一个使用 @FXML
注入的成员节点,您永远不应使用 new
构造函数创建新对象实例并将该新对象分配给现有引用。而只是使用 FXML 为您创建的对象。
你有:
@FXML
private ImageView img_1;
没关系。
然后在 loadImg 中,您有:
img_1 = new ImageView();
img_1.setImage(newImg);
太糟糕了。
您已经有一个 ImageView,它是 FXMLLoader 在您加载 FXML 文档时为您创建的。 FXML Loader 然后将该 ImageView 分配给您的 img_1
引用,因为您使用了 @FXML
注释。
如何修复
所以您需要做的就是停止创建新的 ImageView,只写:
img_1.setImage(newImg);
大功告成。
为什么有效
ImageView 的图像 属性 是可观察的 属性。 JavaFX 系统会观察 Image 属性 是否有任何变化,如果发生变化,则会自动更新显示在 ImageView 屏幕上的图像。您不需要执行任何重绘调用(在任何情况下都没有这样的重绘例程可以调用)。
背景阅读
如果你想更好地理解JavaFX场景图架构,阅读Oracle教程就可以了:
一些小技巧
- 您可以create a JavaFX image directly from an InputStream,您不需要为此任务使用 ImageIO 和 SwingFXUtils。
- 您可以使用 Task 与数据库通信,您的应用程序可能响应更快。
- 从文件或通过 http 而不是从数据库读取图像可能更简单。
免责声明
除了此处指出的问题外,您未提供的代码中可能存在其他错误,这可能会阻止您的应用程序按您希望的方式运行。
Java我毕业于此:
在我的 JavaFX 学期项目中,我必须在 setOnAction 事件(单击按钮)时更新 imageView 对象。这允许程序用户点击一系列图片。
以下效果很好:
首先创建您的 Image 和 ImageView 实例:
Image imageObject = new Image();
ImageView imageViewObject = new ImageView();
然后在代码中向下一个按钮事件导致(下一个)图像被分配和更新如下:
btn.setOnAction(e -> {
imageIndex++;
imageFilename = imageNamesArray.get(imageIndex);
imageObject = new Image(imageFilename);
imageViewObject.setImage(imageObject);
}
注意:我项目中的文件名是 jpg 文件(名称),保存为 ArrayList() 中的字符串元素。单击按钮还会将数组索引递增到下一个 jpg 文件名(和路径或 URL),并且新图像将出现。
因此,在上述答案中,您只创建了一个 ImageViewObject,但每次都将新图像重新分配给图像对象 "imageObject"。
基本上我有一种方法可以将图像从数据库加载到 imageView 中,还有第二种方法可以更改图像我很成功 运行 这两种方法都没有出现异常,但是在 changeImage() 中的 setImage 之后方法我需要更新什么以及(场景,舞台)怎么可能。我知道在 javafx 的 swing 中没有像 repaint() 这样的方法,那么我该如何处理呢?
public class MainMenuController implements Initializable {
/**
* Initializes the controller class.
*/
@Override
public void initialize(URL url, ResourceBundle rb) {
// TODO
}
private AnchorPane stck1;
@FXML
private AnchorPane openSecondWindow(ActionEvent event) throws Exception {
GUIController ctrl = new GUIController();
Stage stage = new Stage();
setStck1((AnchorPane) FXMLLoader.load(InteractiveFictionGame2.class.getResource("GUI.fxml")));
ImageView img_1 = new ImageView(ctrl.loadImg().getImage());
img_1.setPreserveRatio(true);
img_1.setSmooth(true);
img_1.setCache(true);
getStck1().getChildren().add(img_1);
Scene scene = new Scene(getStck1());
stage.setTitle("Interactive Fiction Game");
stage.setScene(scene);
stage.setFullScreen(true);
// stage.sizeToScene();
stage.show();
return getStck1();
}
public class GUIController implements Initializable {
@FXML
private TabPane tb1;
/**
* Initializes the controller class.
*
* @param url
*/
@Override
public void initialize(URL url, ResourceBundle rb) {
// TODO
}
@FXML
private ImageView img_1;
public ImageView loadImg() {
try {
con = DriverManager.getConnection(host, unm, pswrd);
stmnt = con.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_READ_ONLY);
rs = stmnt.executeQuery(SQL);
rs.next();
fis = rs.getBinaryStream(4);
imgt = javax.imageio.ImageIO.read(fis);
Image newImg = SwingFXUtils.toFXImage(imgt, null);
img_1 = new ImageView();
img_1.setImage(newImg);
rs.close();
stmnt.close();
con.close();
} catch (Exception e) {
System.out.println("Not working");
}
return img_1;
}
public void changeImage() {
..
fis = rs.getBinaryStream(1);
imgt = javax.imageio.ImageIO.read(fis);
Image newImg = SwingFXUtils.toFXImage(imgt, null);
img_1.setImage(newImg);
...
} catch (Exception e) {
System.out.println("Not working");
}
return img_1;
}
您的问题
如果您的控制器中有一个使用 @FXML
注入的成员节点,您永远不应使用 new
构造函数创建新对象实例并将该新对象分配给现有引用。而只是使用 FXML 为您创建的对象。
你有:
@FXML
private ImageView img_1;
没关系。
然后在 loadImg 中,您有:
img_1 = new ImageView();
img_1.setImage(newImg);
太糟糕了。
您已经有一个 ImageView,它是 FXMLLoader 在您加载 FXML 文档时为您创建的。 FXML Loader 然后将该 ImageView 分配给您的 img_1
引用,因为您使用了 @FXML
注释。
如何修复
所以您需要做的就是停止创建新的 ImageView,只写:
img_1.setImage(newImg);
大功告成。
为什么有效
ImageView 的图像 属性 是可观察的 属性。 JavaFX 系统会观察 Image 属性 是否有任何变化,如果发生变化,则会自动更新显示在 ImageView 屏幕上的图像。您不需要执行任何重绘调用(在任何情况下都没有这样的重绘例程可以调用)。
背景阅读
如果你想更好地理解JavaFX场景图架构,阅读Oracle教程就可以了:
一些小技巧
- 您可以create a JavaFX image directly from an InputStream,您不需要为此任务使用 ImageIO 和 SwingFXUtils。
- 您可以使用 Task 与数据库通信,您的应用程序可能响应更快。
- 从文件或通过 http 而不是从数据库读取图像可能更简单。
免责声明
除了此处指出的问题外,您未提供的代码中可能存在其他错误,这可能会阻止您的应用程序按您希望的方式运行。
Java我毕业于此:
在我的 JavaFX 学期项目中,我必须在 setOnAction 事件(单击按钮)时更新 imageView 对象。这允许程序用户点击一系列图片。
以下效果很好:
首先创建您的 Image 和 ImageView 实例:
Image imageObject = new Image();
ImageView imageViewObject = new ImageView();
然后在代码中向下一个按钮事件导致(下一个)图像被分配和更新如下:
btn.setOnAction(e -> {
imageIndex++;
imageFilename = imageNamesArray.get(imageIndex);
imageObject = new Image(imageFilename);
imageViewObject.setImage(imageObject);
}
注意:我项目中的文件名是 jpg 文件(名称),保存为 ArrayList() 中的字符串元素。单击按钮还会将数组索引递增到下一个 jpg 文件名(和路径或 URL),并且新图像将出现。 因此,在上述答案中,您只创建了一个 ImageViewObject,但每次都将新图像重新分配给图像对象 "imageObject"。