[英]How to update a java swing gui witha server from another thread?
I have this Java Swing application that starts a new thread that uses a executor pool to open a socket server every time a incomming client tries to establish a connection. 我有这个Java Swing应用程序,它启动一个新线程,每当一个incomming客户端尝试建立连接时,它使用一个执行器池来打开一个套接字服务器。
The application need two buttons, one to start and another to stop the server. 应用程序需要两个按钮,一个用于启动,另一个用于停止服务器。 What I want is to show the server status, and disable the opposed button until its status changes.
我想要的是显示服务器状态,并禁用相反的按钮,直到其状态更改。
This is what I have by now, but I don't know how could I communicate with the EDT when the thread stops. 这就是我现在所拥有的,但我不知道如何在线程停止时与EDT通信。 What I can do is just check the
isRunning()
method. 我能做的就是检查
isRunning()
方法。
Would it be better to use a SwingWorker? 使用SwingWorker会更好吗?
public class ServerManager implements Runnable {
private Executor mExecutor = Executors.newSingleThreadExecutor();
private ServerSocket mServerSocket = null;
private int mDefaultPort = 43012;
private volatile boolean isRunning = false;
public ServerManager (int port){
mDefaultPort = port;
}
@Override
public void run() {
try {
mServerSocket = new ServerSocket(mDefaultPort);
isRunning = true;
while (isRunning){
mExecutor.execute(new IncomingClientThread(mServerSocket.accept()));
}
} catch (IOException e) {
e.printStackTrace();
} finally {
if(mServerSocket != null){
stop();
System.out.println("Server closed");
}
}
}
public void stop(){
try {
mServerSocket.close();
isRunning = false;
} catch (IOException e) {
throw new RuntimeException("Error closing server", e);
}
}
public synchronized boolean isRunning() {
return isRunning;
}
public int getServerPort (){
return mDefaultPort;
}
}
And this is what I have in the GUI thread: I'm using just one button and changing its text everytime it's pressed, but if the server disconnects for some reason, the button stays the same. 这就是我在GUI线程中所拥有的:我只使用一个按钮并在每次按下时更改其文本,但如果服务器由于某种原因断开连接,则按钮保持不变。
connectButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
if(mServer.isStopped()){
new Thread (mServer).start();
connectButton.setText("Desconectar");
infoLabel.setText("Servidor online en IP: " + NetworkUtils.getLocalIpAddress()
+ " puerto: " + mServer.getServerPort());
System.out.println(mServer.getIpAddress());
}else{
mServer.stop();
connectButton.setText("Conectar");
infoLabel.setText("Offline");
}
}
});
Any help is wellcome! 任何帮助都很好! Thanks.
谢谢。
One possible solution is to give it part of the functionality of a SwingWorker -- give it a SwingPropertyChangeSupport object, and allow your GUI to listen for and respond to state changes. 一种可能的解决方案是为SwingWorker提供部分功能 - 为其提供SwingPropertyChangeSupport对象,并允许GUI监听和响应状态更改。
eg, 例如,
public class ServerManager implements Runnable {
public static final String IS_RUNNING = "is running"; // for the Event's name
private SwingPropertyChangeSupport propChngSupport = new SwingPropertyChangeSupport(this);
private volatile boolean isRunning = false;
// other variables
// addPropertyChangeListener(...) {...} goes here
// removePropertyChangeListener(...) {...} goes here
public void setIsRunning(boolean isRunning) {
boolean newValue = isRunning;
boolean oldValue = this.isRunning;
this.isRunning = isRunning;
propChngSupport.firePropertyChange(IS_RUNNING, oldValue, newValue);
}
public void run() {
// ....
}
// other methods
}
The key being to never change the isRunning property outside of its setter method. 关键是永远不要在其setter方法之外更改isRunning属性。
So, what I've done as was recommnded by @Hovercraft Full Of Eels was: 所以,@ Hovercraft Full Of Eels推荐的我所做的是:
In the threaded class: 在线程类中:
public class ServerManager implements Runnable {
...
public static final String IS_RUNNING = "IS_RUNNING";
private SwingPropertyChangeSupport pChange = new SwingPropertyChangeSupport(this);
public void setIsRunning (boolean isRunning){
boolean newValue = isRunning;
boolean oldValue = this.isRunning;
this.isRunning = isRunning;
pChange.firePropertyChange(IS_RUNNING, oldValue, newValue);
}
public void addPropertyChangeListener (PropertyChangeListener listener){
pChange.addPropertyChangeListener(IS_RUNNING, listener);
}
public void removePropertyChangeListener(PropertyChangeListener listener){
pChange.removePropertyChangeListener(IS_RUNNING, listener);
}
...
}
And in the GUI class: 在GUI类中:
public class StatusPane extends JPanel{
private ServerManager mServer;
public StatusPane() {
...
mServer = new ServerManager();
mServer.addPropertyChangeListener(new PropertyChangeListener() {
public void propertyChange(PropertyChangeEvent evt) {
System.out.println(evt.getPropertyName() + " cambia su valor de "
+ evt.getOldValue() + " a " + evt.getNewValue());
}
});
...
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.