gpt4 book ai didi

JavaFX 阻止 UI(和代码)直到服务器调用完成

转载 作者:行者123 更新时间:2023-12-01 18:23:20 24 4
gpt4 key购买 nike

这个主题存在于无数“在长时间持续调用耗时的内容(服务器)期间不阻塞 JavaFX UI”的文章中。我知道这一点,我用谷歌搜索并尝试了很多。大多数“互联网”解释说,由JavaFX事件引起的持久调用需要在额外的线程中进行。线程完成后,您可以通过 Platform.runLater() 使用结果更新 FX UI。大多数 FX 库都用复杂的代码结构封装了这一点(非常酷的东西)。我当前的问题是:我们正在将 Swing 富客户端迁移到 JavaFX。它是一个巨大的客户端,因此我们必须不断地在其中包含/替换 JavaFX UI,直到它成为一个完整的 FX 客户端。客户端中有一些功能会执行服务器调用,并且必须等待用户才能继续其工作。服务器使用带有无状态 session bean 和接口(interface)的 JEE6。这些接口(interface)对于客户端来说是已知的,并且通过我们自己的一个小库,我们实现了一个小代理,对客户端隐藏了通信层。客户端只需使用库创建一个“RemoteProxy”,然后调用远程接口(interface),库将调用传播到服务器。调用该方法并将结果或异常传输回客户端。对于客户端来说,这看起来就像本地调用。问题就在这里。典型的代码片段如下所示:

...
ServerRemoteInterface myServerRemoteProxy = Helper.getProxyForInterface(ServerRemoteInterface.class) ;
...
ComplexResult result = myServerRemoteProxy.doThingsOnServer(SerializableParameter p1 ...)
doSomethingUsefull() ;

对服务器的调用在 Swing UI 线程中触发(通过监听器)。它停止程序(监听器代码)的执行,尽管它是在额外的线程中完成的。服务器返回后调用“doSomethingUsefull()”。开发人员不必关心这里的线程。它是如何实现的?通过使用“旋转库”(http://spin.sourceforge.net/)。它对 Swing EDT 做了一些巧妙的处理。另一种选择是使用模态对话框,但我们决定不使用额外的窗口,而是使用玻璃 Pane 来禁用一些 UI 组件。

这么长的解释和简短的问题......JavaFX 是否有类似的东西可以帮助我们无缝调用服务器、停止程序执行直到它返回并且不阻塞 JavaFX UI?如果它可以与 Java Swing 部分代码一起工作那就最好了。

编辑...添加一个非常压缩的示例来演示隐藏 JDialog 的使用。

我们需要服务器远程接口(interface)。任何接口(interface)都可以。

public interface ServerRemoteInterface
{
public String method1() ; // String result in our case for test purposes
public String method2() ; // Exceptions would also be possible.
}

然后我们需要代理调用处理程序

public class ServerProxy implements InvocationHandler
{
public Object result;
JDialog modalDialog = new JDialog((Frame)null, true);

@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable
{
ServerCallHelper serverThread = new ServerCallHelper(args, method) ;
modalDialog.setLocation(4000, 5000); // as if using Spin library. Here we use the dialog to block in a location off the screen.
serverThread.start();
modalDialog.setVisible(true) ;
return result;
}

class ServerCallHelper extends Thread
{
Object[] args;
Method method;

public ServerCallHelper(Object[] args, Method method)
{
this.args = args;
this.method = method;
}

public void run()
{
// do a server call via rmi or tunnel it via http, REST or whatever and provide the call parameters. On the server side there must be a receiver propagating the call to the wanted session bean.
// here we just do a simulation
try
{
Thread.sleep(3000);
} catch (InterruptedException e)
{
// interupt is ok here.
}

// now hand the result from the call back. we simulate a fix result
// We also could have caught the Exception and deal with it.
result = "Simulated Result" ;
// Since we are in the worker thread => inform EDT To close the dialog.
SwingUtilities.invokeLater(()->modalDialog.setVisible(false));
}

}

}

最后是一些展示功能的代码

public class SampleUI extends JFrame
{
JButton serverCallButton = new JButton("Call server") ;
JLabel resultLabel = new JLabel("No result so far") ;
public SampleUI()
{
JPanel cont = new JPanel() ;
cont.add(serverCallButton) ;
cont.add(resultLabel) ;
this.setContentPane(cont);

serverCallButton.addActionListener((e)->processServerButtonCall());

}

private void processServerButtonCall()
{
ServerRemoteInterface serverAccess = (ServerRemoteInterface) Proxy.newProxyInstance(SampleUI.class.getClassLoader(), new Class[]{ServerRemoteInterface.class}, new ServerProxy());

String result = serverAccess.method1() ;
resultLabel.setText(result);


}

public static void main(String[] args)
{
SampleUI sampleUI = new SampleUI() ;
sampleUI.pack();
sampleUI.setVisible(true);
}


}

这个例子非常压缩,但应该展示原理。作为开发人员,我不必关心对服务器的调用实际上是服务器调用。对我来说,这就像调用本地电话一样。我什至不必关心我是否在 EDT 主题中,因为我就是这样。正如我所说,在 FX 中,它的工作方式与模态阶段相同。我尝试将其设置为不透明 0.0 => 无论如何它都没有绘制。这有效。

问题仍然存在:有没有办法绕过额外的 JDialog 或 Stage ?

最佳答案

如果我正确理解你的意图,这是 Future 的一个用例:

CompletableFuture.supplyAsync(() -> myServerRemoteProxy.doThingsOnServer(...))
.thenAccept(result -> doSomethingUseful(result));

服务器调用和 doSomethingUseful 都会在另一个线程中执行,因此如果需要,您需要在 doSomethingUseful 中使用 Platform.runLater访问场景图。

关于JavaFX 阻止 UI(和代码)直到服务器调用完成,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27015463/

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