Image 当Platform.runLater调用函数时,JavaFX映像未更改
我有一个在JavaFX GUI中更改图像及其不透明度的功能:Image 当Platform.runLater调用函数时,JavaFX映像未更改,image,javafx,Image,Javafx,我有一个在JavaFX GUI中更改图像及其不透明度的功能: private static Image image = null; private static ImageView imageView = new ImageView(); // some code to add image in GUI public static void changeImage() { imageView.setOpacity(0.5); imageView.setImage(nul
private static Image image = null;
private static ImageView imageView = new ImageView();
// some code to add image in GUI
public static void changeImage() {
imageView.setOpacity(0.5);
imageView.setImage(null);
}
在JavaFX实例中调用此函数时,如果我使用图像而不是setImage()的null
,则图像将消失或正在更改。我试着按下一个按钮来调用这个函数
在这种情况下,一切都如我所料
当我从另一个类调用此函数时,实际图像将更改其不透明度,但图像本身永远不会更改。我按以下方式调用该函数:
public static void changeImg() {
Platform.runLater(() -> FX_Gui.changeImage());
}
正在更改标签、进度条。。。所有这些都可以工作,但我没有设法更改图像。与此同时,我发现没有更改图像的原因是我在GUI初始化完成之前运行了changeImage()。如果我在发送changeImage()命令之前等待500毫秒,一切正常 下面是演示我遇到的问题的最基本的代码:
import javafx.application.Application;
import javafx.application.Platform;
import javafx.embed.swing.JFXPanel;
public class Control_Min {
public static void changeImg() {
Platform.runLater(() -> Fx_Min.changeImage());
}
public static void main(String[] args) {
new Thread() {
public void run() {
Application.launch(Fx_Min.class);
}
}.start();
// JFXPanel will initialize the JavaFX toolkit.
new JFXPanel();
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
changeImg();
}
}
以及Gui本身:
public class Fx_Min extends Application {
private static Stage stage;
private static GridPane rootPane;
private static Scene scene;
private static Image image = null;
private static ImageView imageView = new ImageView();
@Override
public void start(Stage primaryStage) {
stage = primaryStage;
rootPane = new GridPane();
scene = new Scene(rootPane,800,600);
try {
image = new Image(new FileInputStream("C:\\Users\\Peter\\eclipse-workspace\\FX_Test\\src\\application\\Image1.jpg"));
} catch (FileNotFoundException e1) {
e1.printStackTrace();
}
imageView.setImage(image);
rootPane.add(imageView, 1, 0);
stage.setScene(scene);
stage.setResizable(true);
stage.show();
System.out.println("Gui is ready");
}
public static void changeImage() {
try {
image = new Image(new FileInputStream("C:\\Users\\Peter\\eclipse-workspace\\FX_Test\\src\\application\\Image2.jpg"));
} catch (FileNotFoundException e) {
e.printStackTrace();
}
imageView.setImage(image);
System.out.println("Image Changed");
}
public static void main(String[] args) {
launch(args);
}
}
这段代码运行良好。
在控制台中,我得到:Gui已准备就绪
形象改变 当我移除线程时。sleep(500)图像不会改变。 在控制台中,我得到:
图像更改
Gui已准备就绪
我的结论是,我已经在FX运行时初始化之前发送了runlater方法。
(尚未修复静态问题,因为这不是问题所在。我将稍后在原始程序中进行修复。) 我的任务如下:
我在我的电脑上为我的互联网收音机播放器编程一个GUI。 GUI控制收音机并轮询正在播放的内容。 我也想用红外线遥控器控制收音机。 我已经有了一个与遥控器通信的树莓Pi。
因此,我的计划是在PC上运行一个服务器套接字,它接收来自Raspberry Pi的命令。 服务器将在其自己的线程中运行。我想使用runLater命令来更新GUI。 是否有更好的方法从服务器更新GUI? 目标是当我按下遥控器上的按钮时,GUI将立即更新。
根据我对JavaFX的最新了解,我现在将直接在FX类中启动应用程序,并从FX类启动服务器线程 一般来说,JavaFX中的GUI在执行时是自包含和非线性的。将外部方法编程为假定GUI的某个状态,然后根据该假定直接操作GUI不是正确的方法。因此,任何试图通过在
Thread.sleep()
调用中偷懒来了解GUI状态的尝试本质上都是不正确的
不需要调用newjfxpanel()
,因为Application.launch()
将初始化JavaFX。这大概是在sleep(500)
被放入之前添加的,因为如果在Thread.start()
命令之后立即运行,调用changeImg()
将失败,因为launch()
甚至没有时间启动
如前所述,在屏幕完成初始化后,应在FX_Min.start(Stage)
方法中更换某种启动映像,尽管您甚至不太可能看到第一个映像
这个问题似乎旨在设计一种应用程序,其中GUI只是其中的一小部分,主应用程序将继续执行冗长的处理,然后触发GUI以响应处理结果。或者,主应用程序可能正在监视外部API并定期向GUI提供更新。然而,在大多数情况下,GUI通常是初始化的,以便它能够控制操作,启动后台线程进行冗长的处理,并使用JavaFX工具处理GUI更新的触发和结果的接收
如果设计确实需要GUI以外的东西作为中央控制,那么使用Application
似乎并不合适。毕竟,它设计用于控制应用程序,并在GUI启动后监视GUI的状态,以便在GUI关闭时关闭所有内容。这就是为什么OP必须将Application.launch()
调用放在一个单独的线程中-launch()
在GUI关闭之前不会返回
如果GUI之外的应用程序要控制一切,那么最好使用Platform.startup()
手动启动JavaFX,并手动处理所有监控。以下代码不进行任何监视,但它会启动GUI并更改图像,而不会出现任何问题:
public class Control_Min {
public static void main(String[] args) {
Platform.startup(() -> new Fx_Min().start(new Stage()));
Platform.runLater(() -> Fx_Min.changeImage());
}
}
请注意,Fx\u Min
中的OP代码无需更改。但是,Fx_Min
没有理由再扩展应用程序
,它的start()
方法中的代码可以放在任何地方
应该进一步注意的是,尽管这是可行的,但它确实远远超出了JavaFX应用程序的标准。OP的情况可能确实需要这种体系结构,但这将使它成为一小部分应用程序。围绕application.launch()
设计应用程序,并通过提供的JavaFX工具在后台线程中启动冗长的处理,几乎总是一种更好的方法
好的,如果OP提供了新的信息,很明显这应该基于
应用程序
,GUI应该启动某种套接字侦听器,可能会阻止等待输入
任何阻塞的东西都不能在FXAT上运行,需要有一种方法允许套接字侦听器在接收数据时与GUI通信。理想情况下,套接字侦听器应该是JavaFX,而不是普通的Java
在国际海事组织,最好的办法是提供<
public class Fx_Min extends Application {
@Override
public void start(Stage primaryStage) {
ImageView imageView = new ImageView(new Image("/images/ArrowUp.png"));
Text text = new Text("");
primaryStage.setScene(new Scene(new VBox(10, imageView, text), 800, 600));
primaryStage.setResizable(true);
primaryStage.show();
imageView.setImage(new Image("/images/Flag.png"));
new SocketListener(socketMessage -> Platform.runLater(() -> text.setText(socketMessage))).startListening();
}
public static void main(String[] args) {
launch(args);
}
}
public class SocketListener {
private Consumer<String> messageConsumer;
public SocketListener(Consumer<String> messageConsumer) {
this.messageConsumer = messageConsumer;
}
public void startListening() {
Thread listenerThread = new Thread(() -> listenForIRCommand());
listenerThread.setDaemon(true);
listenerThread.start();
}
private void listenForIRCommand() {
for (int x = 0; x < 100; x++) {
try {
Thread.sleep(5000);
messageConsumer.accept("Station " + x);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}