java JavaFX 在 ImageView 中播放 gif 图像

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/46980711/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-11-03 09:27:19  来源:igfitidea点击:

JavaFX play gif image in ImageView

javaxmljavafx

提问by

I see this question asked a lot but I have not seen a very general way of doing it. I am working on a Desktop app in Java Eclipse Oxygen using JavaFX and I have a loader that I want to show whenever and image is loading via http. An image has to be loaded via http when a user clicks on different rows. So I have my loader on top of the image and I just use; productPreviewLoader.setVisible(true)to show it or hide it. The loader ImageView in fxml looks like this in GridPane.

我看到这个问题问了很多,但我还没有看到一个非常通用的方法。我正在使用 JavaFX 在 Java Eclipse Oxygen 中开发桌面应用程序,并且我有一个加载器,我想在通过 http 加载图像时显示它。当用户单击不同的行时,必须通过 http 加载图像。所以我在图像顶部有我的加载器,我只是使用;productPreviewLoader.setVisible(true)显示或隐藏它。fxml 中的加载器 ImageView 在 GridPane 中看起来像这样。

<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>

And the code that sets up the loader image looks like this;

设置加载程序图像的代码如下所示;

//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);

The image does not play in the ImageView. If it is not possible please show me another way of doing it. Also I am having a problem to get the ImageView to center the ImageView horizontally in the GridPane row. The GridPane resizes to match the height of it's parent whenever the window is resized. I know this is 2 questions but I would probably have ended up creating 2 questions.

图像不在 ImageView 中播放。如果不可能,请告诉我另一种方法。另外,我在让 ImageView 在 GridPane 行中水平居中 ImageView 时遇到问题。每当调整窗口大小时,GridPane 都会调整大小以匹配其父级的高度。我知道这是 2 个问题,但我可能最终会创建 2 个问题。

回答by JKostikiadis

Well you haven't provide a complete example that I can use in order to show the use cases of how you can load an gif image to an ImageView so I will give you a full example :

好吧,您还没有提供一个完整的示例,我可以使用它来展示如何将 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);
        }
    }
}

If all your Images are loaded through URLs then why don't you just use a WebViewer and load the URL instead of using an ImageView? If the gif size is not small that will cause a GUI lag until the gif image is loaded from InputStream in that case you should create the loading process to a background thread but as I said you can avoid all that if you just use a WebViewer.

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