我有 WebSocket 服务器:
@ServerEndpoint(value = "/demoApp")
public class MyWebSocketServer {
@OnMessage
public String onMessage (String message, Session session) throws IOException {
for(Session session1 : Main.sessions){
if(!session1.equals(session)){
session1.getBasicRemote().sendText(message);
}
}
}
}
它会通知除了发送消息的人之外所有已连接的人。
我有一个客户端:
@ClientEndpoint
public class WebSocketClient {
@OnMessage
public void onMessage (String message, Session session) {
System.out.println("[SERVER RESPONSE]: " + message);
MyJFrame.setButtonGrid(message);
}
}
我的 JFrame:
public class MyJFrame extends javax.swing.JFrame {
//some generated stuff
public static void setButtonGrid(String message){
Component[] components = this.getContentPane().getComponents();
int i = 0;
for(Component component : components){
if(component instanceof JButton button){
if("Restart".equals(button.getText())){
continue;
}
if(message.charAt(i) == '*'){
button.setText("");
}
else {
button.setText(message.charAt(i) + "");
}
}
}
}
public static void main(String args[]) {
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
new TTTForm().setVisible(true);
}
});
ClientManager clientManager = ClientManager.createClient();
URI uri = null;
try {
uri = new URI("ws://localhost:8080/java/demoApp");
session = clientManager.connectToServer(WebSocketClient.class, uri);
} catch (URISyntaxException e) {
e.printStackTrace();
} catch (DeploymentException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
但是在
setButtonGrid
方法中我无法获取 JFrame 的组件,显然因为它是静态方法。但如果它不是静态的,那么我将无法从 WebSocket 客户端的类中调用它。那么当信息来自 WebSocket 服务器时,如何更改 JFrame 按钮中的文本?
这里的本质问题是如何让可见的 GUI 实例与套接字客户端进行通信?实现此目的的一种方法是通过 GUI 的构造函数将 GUI 的实例传递到 Web 套接字客户端。然后,使用此 GUI 实例,您可以将数据从客户端传递到 GUI,反之亦然。
假设您有一个如下所示的 GUI:
public class MyJFrame extends javax.swing.JFrame {
// ... code redacted ...
public void fromServer(final String message) {
// note that fromServer will of necessity be called *off* of the Swing event thread, the EDT
// and so you will want to take steps to make sure that it is only used *on* this thread:
EventQueue.invokeLater(new () -> {
// use message from the GUI here
});
}
public static void main(String args[]) {
java.awt.EventQueue.invokeLater(() -> {
public void run() {
MyJFrame myJFrame = new MyJFrame();
ClientManager clientManager = ClientManager.createClient();
URI uri = null;
try {
uri = new URI("ws://localhost:8080/java/demoApp");
// create our WebSocketClient, passing in the GUI
WebSocketClient webSocketClient = new WebSocketClient(myJFrame);
// and then initiate the session using the above client
// This uses an overload of the connectToServer method that takes an object
session = clientManager.connectToServer(webSocketClient, uri);
myJFrame.setVisible(true); // start the GUI
} catch (URISyntaxException e) {
e.printStackTrace();
} catch (DeploymentException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
}
}
你的网络套接字客户端可能看起来像这样:
@ClientEndpoint
public class WebSocketClient {
private MyJFrame myJFrame;
public WebSocketClient(MyJFrame myJFrame) {
this.myJFrame = myJFrame;
}
@OnMessage
public void onMessage (String message, Session session) {
System.out.println("[SERVER RESPONSE]: " + message);
// MyJFrame.setButtonGrid(message); // don't call a static method but rather an instance method
myJFrame.fromServer(message);
}
}
注:
setButtonGrid(...)
而我在这里称之为 fromServer(...)
)成为静态方法。它应该是一个实例方法,以便它可以与您的 GUI 实例交互。EventQueue.invokeLater(someRunnable)
但如果我自己这样做,我可能会使用 SwingWorker,使用工作人员的发布/处理方法对传递数据。