gpt4 book ai didi

JavaFX:AnimationTimer与MenuBar的交互

转载 作者:塔克拉玛干 更新时间:2023-11-02 08:14:00 25 4
gpt4 key购买 nike

我正在开发一种软​​件,它从相机获取图像并将其实时显示在 JavaFX ImageView 中。我有一个获取最后一张图像的线程(在本例中为 BufferedImage),以及一个将其分配给 ImageViewAnimationTimer。我继续使用 AnimationTimer 的原因是它似乎比每次获取新图像时都用 Runnable 填充平台更好。刷新工作正常,FPS 也不错。

但是,我注意到当 AnimationTimer 运行时,我的软件中的菜单栏显示不正确。当我将鼠标悬停在其他菜单项上时,一些菜单项丢失了。这张图解释了它: enter image description here

在左侧,您可以看到菜单通常的样子,而在右侧,则是 AnimationTimer 运行时的样子。如您所见,“保存”菜单项不见了,取而代之的是显示我的实时图像的背景。此外,当我打开一个新窗口(在一个新的 Scene 上)时,当我将鼠标悬停在任何类型的 Node(一个按钮,一个复选框...)上时,背景变黑了。我能够通过在初始化 Scene 时将深度缓冲区 boolean 值设置为 true 来解决这个问题。然而,我不知道如何修复这个菜单栏错误,我认为这些错误表明我正在做的事情可能是不正确的。

我当时在想,也许 JavaFX 应用程序线程已经充满了要显示的新图像,而绘制其他元素(例如菜单项)基本上花费了太多时间。

问题:

  1. 这真的是这个错误的来源吗?
  2. 有没有办法改进我的代码,例如使用不同于 AnimationTimer 的东西?

这是重现错误的代码片段。将 start 函数中的两个字符串更改为图像路径。图像应该相对较大(几 MB)。

单击“开始”按钮启动动画计时器。然后尝试打开"file"菜单,并将鼠标悬停在菜单项上。该错误并没有系统地出现,尝试重复上下移动鼠标,它应该会在某个时候出现。

import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.logging.Level;
import java.util.logging.Logger;
import javafx.animation.AnimationTimer;
import javafx.application.Application;
import javafx.embed.swing.SwingFXUtils;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Menu;
import javafx.scene.control.MenuBar;
import javafx.scene.control.MenuItem;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.Pane;
import javafx.stage.Stage;
import javax.imageio.ImageIO;

public class ImageRefresher extends Application {

@Override
public void start(Stage primaryStage) {

//Here change the 2 Strings to a path to an image on your HDD
//The bug appears more easily with large images (>3-4MB)
String pathToImage1 = "/path/to/your/first/image";
String pathToImage2 = "/path/to/your/second/image";

try {
//Image content (contains buffered image, see below)
ImageContent image = new ImageContent(pathToImage1);

//If this line is commented, the bug does not appear
image.setImage(ImageIO.read(new File(pathToImage2)));

//JavaFX class containing nodes (see below)
MainWindow window = new MainWindow(image);

Scene scene = new Scene(window.getPane(), 300, 250);
primaryStage.setTitle("Menu refresh");
primaryStage.setScene(scene);
primaryStage.show();
} catch (IOException ex) {
Logger.getLogger(ImageRefresher.class.getName()).log(Level.SEVERE, null, ex);
}

}

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

public class MainWindow {

private BorderPane pane;
private MenuBar menuBar;
private ImageView displayImage;
private Button startRefreshingButton;

private ImageContent imageContent;
private AnimationTimer animationTimer;

public MainWindow(ImageContent imageContent) {
this.imageContent = imageContent;

//Builds the window's components
buildGraphic();

//The image is reset at each frame
animationTimer = new AnimationTimer() {
@Override
public void handle(long now) {
displayImage.setImage(imageContent.getDisplayableImage());
}
};
}

private void buildGraphic() {
pane = new BorderPane();
menuBar = new MenuBar();

Menu menu = new Menu("File");
menu.getItems().addAll(new MenuItem("Save"),
new MenuItem("Open"),
new MenuItem("Close"));
menuBar.getMenus().add(menu);

displayImage = new ImageView();

startRefreshingButton = new Button("Start");
startRefreshingButton.setOnAction((event) -> {
animationTimer.start();
});

pane.setTop(menuBar);
pane.setCenter(displayImage);
pane.setBottom(startRefreshingButton);
}

public Pane getPane() {
return pane;
}
}

public class ImageContent {

private BufferedImage imageContent;

//Initializes bufferedimage with the path specified
public ImageContent(String pathToImage) throws IOException {
imageContent = ImageIO.read(new File(pathToImage));
}

public void setImage(BufferedImage newImage) {
imageContent = newImage;
}

//Function called by the animation timer to
//get a JavaFX image from a bufferedimage
public Image getDisplayableImage() {
return SwingFXUtils.toFXImage(imageContent, null);
}
}
}

最佳答案

我想问题在于,由于您每帧都在重新绘制图像,因此您将菜单弹出窗口与图像重叠。这似乎是一个错误,但您还要求 FX 应用程序线程执行比您需要的更多的工作。

理想情况下,您应该找到一种方法来检查是否真的有新图像,并且只有在确实有新文件时才更新图像。 (考虑使用 java.nio.file.Path 来表示文件并调用 Files.getLastModifiedTime(path)。)

另一种避免 FX 应用程序线程被过多 Platform.runLater(...) 调用淹没的方法,参见 Throttling javafx gui updates

关于JavaFX:AnimationTimer与MenuBar的交互,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23593164/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com