gpt4 book ai didi

java - 在 JavaFx 应用程序的不同分辨率下闪烁白屏

转载 作者:行者123 更新时间:2023-12-03 12:46:58 26 4
gpt4 key购买 nike

我们正在使用 JavaFx 和 JavaCv 开发视频流应用程序。 我们有 8X8 的 GridPane,每个单元格包含 Pane 布局和每个 Pane 包含 ImageView。

每当用户将 url 拖到特定位置时,我都会调用播放功能 细胞。 我们有 64 个网址,所以我们调用播放函数 64 次(所有 64 个网址都在播放 在后台线程中)。

for(int i=0;i<8;i++){
for(int j=0;j<8;j++){
//grid08(8X8)
Pane p=new Pane();
ImageView im=new ImageView();
Label l=new Label("");
im.fitWidthProperty().bind(p.widthProperty());
im.fitHeightProperty().bind(p.heightProperty());
l.prefWidthProperty().bind(p.widthProperty());
l.prefHeightProperty().bind(p.heightProperty());
p.getChildren().addAll(im,l);
l.setVisible(false);
l.setStyle("-fx-text-fill: #fff; -fx-font-size: 12px");
l.setAlignment(Pos.CENTER);
p.setStyle("-fx-background-color: black;");
grid.add(p,j,i);//grid->instance of gridPane
p.setOnDragOver(new EventHandler<DragEvent>() {
@Override
public void handle(DragEvent event) {
if(!l.isVisible()){
event.acceptTransferModes(TransferMode.ANY);
}
}
});
p.setOnDragDropped(new EventHandler<DragEvent>() {
@Override
public void handle(DragEvent event) {
play(im,event.getDragboard().getString());
}
});
}
}

play(ImageView im,String Url){
new Thread(new Runnable(){
frameGrabber = new FFmpegFrameGrabber(Url);
frameGrabber.setVideoOption("preset","ultrafast");
frameGrabber.setOption("rtsp_transport","tcp");
frameGrabber.setOption("stimeout" , "60000");
frameGrabber.setAudioChannels(0);
frameGrabber.setAudioCodec(0);
try {
frameGrabber.start();
start=true;
} catch (Exception e) {
}
JavaFXFrameConverter jconverter=new JavaFXFrameConverter();
while(true){
Frame frame = frameGrabber.grabImage();
Image image=jconverter.convert(frame);
Platform.runlater(new Runnable(){
im.setImage(image);
});
}
}).start();
}

问题: 在增加一些阈值宽度和 高度。 在这里,我附上了不同屏幕尺寸的应用程序快照; Screen1 Screen2 Screen3 Screen4

屏幕 1

因为我们长期以来一直面临这个问题。 任何潜在客户都将受到高度赞赏。 提前致谢。

最佳答案

这里只是一个猜测,但是当 ImageView 与图像的大小不同时,当您调用 setImage(...) 时 ImageView 有很多工作要做(它必须调整图像大小)。因为你有很多这样的事情发生,可能是每个脉冲,你可能向 Platform.runLater(...) 提交了比它能处理的更多的可运行文件(即你提交了另一个 Platform. runLater(...) 在从同一线程提交的前一个可以完成之前)。这将导致渲染问题,因为渲染系统跟不上。

我无法对此进行测试,所以我不确定它是否会解决问题,但只提交对 Platform.runLater(...) 的新调用可能是个好主意> 当前一个完成时(即即使这不是问题的原因,你也应该这样做)。

你可以这样做

void play(ImageView im,String Url){
new Thread(() -> {
frameGrabber = new FFmpegFrameGrabber(Url);
frameGrabber.setVideoOption("preset","ultrafast");
frameGrabber.setOption("rtsp_transport","tcp");
frameGrabber.setOption("stimeout" , "60000");
frameGrabber.setAudioChannels(0);
frameGrabber.setAudioCodec(0);
try {
frameGrabber.start();
start=true;
} catch (Exception e) {
e.printStackTrace();
}
JavaFXFrameConverter jconverter=new JavaFXFrameConverter();

AtomicReference<Image> imageHolder = new AtomicReference<>(null);
while(true){
Frame frame = frameGrabber.grabImage();
Image image=jconverter.convert(frame);
if (imageHolder.getAndSet(image) == null) {
Platform.runLater(() -> im.setImage(imageHolder.getAndSet(null)));
}
}
}).start();
}

请注意,在此代码(和原始代码)中,所有 图像都在同一个线程(FX 应用程序线程)上调整大小。如果可能的话,在自己的线程中调整每个图像的大小可能会更有效。你不能绝对保证这一点(因为没有办法保证 ImageView 在后台线程中调整大小的图像和显示图像的 ImageView 之间不会改变大小),所以你仍然需要绑定(bind) fitWidthfitHeight 属性,但这应该会减少 UI 线程上发生的图像大小调整量,从而提高性能。这依赖于您的图像采集卡 API(我不熟悉)中的某种机制来调整图像大小。

for(int i=0;i<8;i++){
for(int j=0;j<8;j++){
//grid08(8X8)
Pane p=new Pane();
AtomicReference<Bounds> bounds = new AtomicReference<>(p.getBoundsInLocal());
p.boundsInLocalProperty().addListener((obs, oldBounds, newBounds) -> bounds.set(newBounds));
ImageView im=new ImageView();
Label l=new Label("");
im.fitWidthProperty().bind(p.widthProperty());
im.fitHeightProperty().bind(p.heightProperty());
l.prefWidthProperty().bind(p.widthProperty());
l.prefHeightProperty().bind(p.heightProperty());
p.getChildren().addAll(im,l);
l.setVisible(false);
l.setStyle("-fx-text-fill: #fff; -fx-font-size: 12px");
l.setAlignment(Pos.CENTER);
p.setStyle("-fx-background-color: black;");
grid.add(p,j,i);//grid->instance of gridPane
p.setOnDragOver(new EventHandler<DragEvent>() {
@Override
public void handle(DragEvent event) {
if(!l.isVisible()){
event.acceptTransferModes(TransferMode.ANY);
}
}
});
p.setOnDragDropped(new EventHandler<DragEvent>() {
@Override
public void handle(DragEvent event) {
play(im,bounds,event.getDragboard().getString());
}
});
}
}

void play(ImageView im, AtomicReference<Bounds> bounds, String Url){
new Thread(() -> {
frameGrabber = new FFmpegFrameGrabber(Url);
frameGrabber.setVideoOption("preset","ultrafast");
frameGrabber.setOption("rtsp_transport","tcp");
frameGrabber.setOption("stimeout" , "60000");
frameGrabber.setAudioChannels(0);
frameGrabber.setAudioCodec(0);
try {
frameGrabber.start();
start=true;
} catch (Exception e) {
e.printStackTrace();
}
JavaFXFrameConverter jconverter=new JavaFXFrameConverter();

AtomicReference<Image> imageHolder = new AtomicReference<>(null);
while(true){
Frame frame = frameGrabber.grabImage();

Bounds imgBounds = bounds.get();
double width = imgBounds.getWidth();
double height = imgBounds.getHeight();

// resize frame to width, height....

Image image=jconverter.convert(frame);

if (imageHolder.getAndSet(image) == null) {
Platform.runLater(() -> im.setImage(imageHolder.getAndSet(null)));
}
}
}).start();
}

关于java - 在 JavaFx 应用程序的不同分辨率下闪烁白屏,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50608314/

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