JavaFX中如何在ImageView控件上播放gif图片

3

我经常看到这个问题被问及,但是我还没有看到一个非常通用的解决方式。我正在使用JavaFX和Java Eclipse Oxygen开发桌面应用程序,并且当通过http加载图像时,我有一个加载器要展示。当用户点击不同的行时,必须通过http加载图像。因此,在图像上方放置了加载器,我只需使用productPreviewLoader.setVisible(true)来显示或隐藏它。在GridPane中,fxml文件中的加载器ImageView如下所示。

<GridPane>
   <columnConstraints>
      <ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" />
   </columnConstraints>
   <rowConstraints>
      <RowConstraints minHeight="10.0" valignment="TOP" vgrow="ALWAYS" />
      <RowConstraints vgrow="SOMETIMES" />
      <RowConstraints vgrow="SOMETIMES" />
   </rowConstraints>
   <children>
      <ImageView fx:id="productPreview" fitHeight="282.0" fitWidth="200.0" pickOnBounds="true" preserveRatio="true" />
      <!-- This is the loader-->
      <ImageView fx:id="productPreviewLoader" fitHeight="112.0" fitWidth="136.0" pickOnBounds="true" preserveRatio="true" /> 
      <TextFlow fx:id="productPreviewTextFlow" GridPane.rowIndex="1">
         <GridPane.margin>
            <Insets right="10.0" />
         </GridPane.margin>
         <padding>
            <Insets bottom="30.0" left="10.0" right="10.0" top="30.0" />
         </padding></TextFlow>

设置加载图像的代码如下:

//Set up the product preview image loader
BufferedImage bufferedImage;
File file = new File("resources\\images\\loaders\\img-loader-icon.gif");
try {
bufferedImage = ImageIO.read(file);
   productPreviewLoader.setImage(SwingFXUtils.toFXImage(bufferedImage, null));
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
productPreviewLoader.setVisible(false);
中的图像无法在ImageView中播放。如果不可能,请向我展示另一种方法。此外,我在将ImageView水平居中于GridPane行时遇到了问题。每当窗口大小调整时,GridPane会调整大小以匹配其父级的高度。我知道这是两个问题,但我可能最终会创建两个问题。
1个回答

2

您还没有提供一个完整的例子,以便我展示如何加载gif图像到ImageView的用例,所以我将给您一个完整的例子:

import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.net.URLConnection;

import javafx.application.Application;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.layout.FlowPane;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;

public class GifViewerTest extends Application {

    public static void main(String[] args) {
        launch(args);
    }

    @Override
    public void start(Stage stage) throws Exception {

        VBox box = new VBox();
        ImageView imageView = new ImageView();

        box.getChildren().add(imageView);

        Button localLoadButton = new Button("Local load");
        Button externalLoadButton = new Button("URL Load");

        localLoadButton.setOnAction(e -> {
            imageView.setImage(new Image(this.getClass().getResource("java.gif").toExternalForm()));
        });

        externalLoadButton.setOnAction(e -> {
            String imageSource = "https://cdn.dribbble.com/users/550761/screenshots/1773241/untitled-5.gif";
            try {
                imageView.setImage(createImage(imageSource));
            } catch (IOException e1) {
                e1.printStackTrace();
            }
        });

        FlowPane buttonPane = new FlowPane();
        buttonPane.setAlignment(Pos.CENTER);
        buttonPane.getChildren().addAll(localLoadButton, externalLoadButton);

        box.getChildren().add(buttonPane);

        stage.setScene(new Scene(box, 500, 400));
        stage.show();
    }

    private Image createImage(String url) throws IOException {
        // You have to set an User-Agent in case you get HTTP Error 403
        // respond while you trying to get the Image from URL.
        URLConnection conn = new URL(url).openConnection();
        conn.setRequestProperty("User-Agent", "Wget/1.13.4 (linux-gnu)");

        try (InputStream stream = conn.getInputStream()) {
            return new Image(stream);
        }
    }
}

如果您的所有图片都是通过URL加载的,那么为什么不使用WebViewer并加载URL,而不是使用ImageView?如果gif大小不小,则会导致GUI滞后,直到从InputStream加载gif图像,在这种情况下,您应该将加载过程创建为后台线程,但正如我所说,如果您只使用WebViewer,可以避免所有这些问题。

看这段代码,我没有看到你在哪里设置git动画播放。除了添加按钮来加载图像之外。我没有问题加载图像。但是当将图像添加到ImageView时,它不会播放。它停留在第一帧。 - user5500750
你所说的“play”具体是什么意思?当你使用上述代码并点击“URL Load”按钮时,你应该能够看到gif图像。externalLoadButton通过URL将gif图像加载到ImageView中。也许我没有理解你的目标...如果我错了,请纠正我。 - JKostikiadis
gif图像包含动画。在我的代码中,当我使用productPreviewLoader.setImage(SwingFXUtils.toFXImage(bufferedImage, null));时,图像只是静止的,没有动画。 - user5500750
当然可以。上面的代码正在播放一个动画gif图像,您可以在此链接中找到它。为了播放动画图像,您可以通过资源加载方式或直接通过URL加载。您是说使用我提供的代码仍然无法看到动画吗? - JKostikiadis
很奇怪,我觉得我做得过头了。所以只需要执行 productPreviewLoader.setImage(new Image("file:resources\\images\\loaders\\img-loader-icon.gif")); 就可以加载一个播放图像。在你的回答中,我认为这对于本地图片不起作用 this.getClass().getResource("java.gif").toExternalForm() 我猜你是想加载本地图片而不是通过HTTP加载图片。 - user5500750
本地加载gif对我来说也很顺利。当然,你需要将图像放置在正确的路径上,以便从资源中加载它。在上面的示例中,我将gif图像放置在与默认包中的Java类相同的目录中,如果您将图像添加到不同的目录/包中(而且您应该这样做),则应设置完整路径。 - JKostikiadis

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接