我正在制作一个客户端 - 服务器Java应用程序,它将成为MV(C,P)。我当前的问题是,一旦客户端得到一个Player对象,它需要告诉GUI播放器已被更改,它应该更新GUI上的所有内容。 (不太详细,所以整个更新应该不错)
/*
* ClientGUI.java
*
* Created on Dec 10, 2009, 7:51:31 PM
*/
package inequity;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.Socket;
import java.util.concurrent.PriorityBlockingQueue;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
*
* @author Administrator
*/
public class ClientGUI extends javax.swing.JFrame
{
private Socket socClient;
private ObjectOutputStream socketOut;
private ObjectInputStream socketIn;
PriorityBlockingQueue<Command> clientQ = null;
private Player me;
public ClientGUI()
{
initComponents();
setDefaultCloseOperation(javax.swing.JFrame.EXIT_ON_CLOSE);
clientQ = new PriorityBlockingQueue<Command>(Server.CLIENT_QUEUE_SIZE, new CompObj());
me = new Player();
}
public void initPlayer(String name, String color)
{
me.name = name;
me.color = color;
}
public boolean connect(int port)
{
try
{
socClient = new Socket("127.0.0.1", port);
if(socClient.isConnected())
System.out.println("Connected");
socketOut = new ObjectOutputStream(socClient.getOutputStream());
socketIn = new ObjectInputStream(socClient.getInputStream());
socketOut.writeObject(new PlayerUpdate(me, 2));
new ClientListener(socketIn).start();
}
catch(Exception e)
{
try
{
if(socketOut != null)
{
socketOut.flush();
socketOut.close();
}
if(socketIn != null)
{
socketIn.close();
}
System.out.println("Unable to connect");
}
catch (IOException ex)
{
System.out.println("IOException caught");
return false;
}
}
return true;
}
/** This method is called from within the constructor to
* initialize the form.
* WARNING: Do NOT modify this code. The content of this method is
* always regenerated by the Form Editor.
*/
@SuppressWarnings("unchecked")
// <editor-fold defaultstate="collapsed" desc="Generated Code">
private void initComponents() {
txtMsg = new javax.swing.JTextField();
btnSend = new javax.swing.JButton();
PlayerName = new javax.swing.JLabel();
ID = new javax.swing.JLabel();
chat = new javax.swing.JLabel();
setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
txtMsg.setText("Test");
txtMsg.setName("txtMsg"); // NOI18N
txtMsg.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
txtMsgActionPerformed(evt);
}
});
btnSend.setText("Send");
btnSend.setName("btnSend"); // NOI18N
btnSend.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
btnSendActionPerformed(evt);
}
});
PlayerName.setText("N/A");
PlayerName.setName("PlayerName"); // NOI18N
ID.setText("ID:");
ID.setName("ID"); // NOI18N
chat.setText("Chatbox");
chat.setName("chat"); // NOI18N
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
getContentPane().setLayout(layout);
layout.setHorizontalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addContainerGap()
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(btnSend, javax.swing.GroupLayout.DEFAULT_SIZE, 149, Short.MAX_VALUE)
.addComponent(txtMsg, javax.swing.GroupLayout.DEFAULT_SIZE, 149, Short.MAX_VALUE)
.addComponent(PlayerName, javax.swing.GroupLayout.DEFAULT_SIZE, 149, Short.MAX_VALUE))
.addContainerGap())
.addGroup(layout.createSequentialGroup()
.addComponent(ID)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 62, Short.MAX_VALUE)
.addComponent(chat)
.addGap(41, 41, 41))))
);
layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
.addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(ID)
.addComponent(chat))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addComponent(PlayerName)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addComponent(txtMsg, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(btnSend)
.addContainerGap())
);
pack();
}// </editor-fold>
private void txtMsgActionPerformed(java.awt.event.ActionEvent evt) {
}
private void btnSendActionPerformed(java.awt.event.ActionEvent evt) {
try
{
if(socketOut != null)
socketOut.writeObject(new ChatCmd(txtMsg.getText(), 10));
}
catch (IOException ex)
{
Logger.getLogger(ClientGUI.class.getName()).log(Level.SEVERE, null, ex);
}
}
/**
* @param args the command line arguments
*/
public static void main(String args[]) {
java.awt.EventQueue.invokeLater(new Runnable() {
public void run()
{
String name = "";
String color = "";
JoinGUI join = new JoinGUI(name, color);
ClientGUI client = new ClientGUI();
client.initPlayer(name, color);
client.setVisible(join.prompt());
client.connect(1345);
}
});
}
// Variables declaration - do not modify
private javax.swing.JLabel ID;
private javax.swing.JLabel PlayerName;
private javax.swing.JButton btnSend;
private javax.swing.JLabel chat;
private javax.swing.JTextField txtMsg;
// End of variables declaration
// End of variables declaration
public class ClientListener extends Thread
{
private ObjectInputStream recieving;
public ClientListener(ObjectInputStream in)
{
recieving = in;
}
@Override
public void run()
{
Command cmd;
while(true)
{
try
{
cmd = (Command) recieving.readObject();
clientQ.add(cmd);
//temp code! Put in clientProxy? Drop to clientQ?
clientQ.take().exec(me);
ID.setText("" + me.getID());
PlayerName.setText("" + me.name);
chat.setText(me.latestChatMsg);
}
catch (InterruptedException ex)
{
Logger.getLogger(ClientGUI.class.getName()).log(Level.SEVERE, null, ex);
}
catch (IOException ex)
{
Logger.getLogger(ClientListener.class.getName()).log(Level.SEVERE, null, ex);
}
catch (ClassNotFoundException ex)
{
Logger.getLogger(ClientListener.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
}
}
package inequity;
import java.io.Serializable;
import java.util.ArrayList;
/**
*
* @author Administrator
*/
public class Player implements Serializable
{
public ArrayList openHandShakes;
public String latestChatMsg;
private int ID;
public String name;
public String color;
public Player()
{
openHandShakes = new ArrayList();
ID = -1;
name = "";
color = "";
}
public void setID(int id)
{
ID = id;
}
public int getID()
{
return ID;
}
public void openHandShake(int shakeID)
{
openHandShakes.add(shakeID);
}
public boolean closeHandShake(int shakeID)
{
return true;
}
public void latestChat(String message)
{
latestChatMsg = message;
}
}
package inequity;
import javax.swing.Box;
import javax.swing.JTextField;
/**
*
* @author Administrator
*/
public class JoinGUI extends javax.swing.JFrame
{
private JTextField nameBox;
private JTextField colorBox;
public JoinGUI(String name, String color)
{
//give back name and color to clientgui
nameBox = new JTextField("Enter Name");
colorBox = new JTextField("Enter Color");
Box inputMenu = Box.createVerticalBox();
inputMenu.add(nameBox);
inputMenu.add(colorBox);
add(inputMenu);
}
public boolean prompt()
{
setVisible(false);
//wait for enter to be pressed then return true, as clientGUI is waiting to started
//then give name and color to client
return true;
}
}
/*
* Server.java
*/
package inequity;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.JFrame;
import java.net.*;
import java.util.concurrent.PriorityBlockingQueue;
/**
* The main class of the application.
*/
public class Server extends JFrame
{
public static final int CLIENT_QUEUE_SIZE = 10;
public static final int SERVER_QUEUE_SIZE = 10;
public Server()
{
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
public PlayerProxy wait4client(int playerID, ServerSocket server, PriorityBlockingQueue<Command> srvQ)
{
Socket incoming;
PriorityBlockingQueue<Command> clientQ = null;
Runnable rIn;
Runnable rOut;
Thread tIn = null;
Thread tOut = null;
try
{
incoming = server.accept();
clientQ = new PriorityBlockingQueue<Command>(CLIENT_QUEUE_SIZE, new CompObj());
rIn = new Net2QRunnable(playerID, incoming, srvQ);
rOut = new Q2NetRunnable(playerID, incoming, clientQ);
tIn = new Thread(rIn);
tOut = new Thread(rOut);
tIn.start();
tOut.start();
}
catch (Exception e)
{
e.printStackTrace();
}
clientQ.add(new HelloMsg());
return new PlayerProxy(playerID, tIn, tOut, clientQ);
}
public static void main(String[] args)
{
PriorityBlockingQueue<Command> srvQ = new PriorityBlockingQueue<Command>(SERVER_QUEUE_SIZE, new CompObj());
try
{
Game game = new Game(srvQ);
Server srv = new Server();
ServerSocket server = new ServerSocket(1345);
srv.setVisible(true);
System.out.println("Lobby");
while (game.numPlayers() < 2)
{
game.addPlayer(srv.wait4client(game.numPlayers(), server, srvQ));
}
game.play();
System.out.println("Game Finished");
}
catch (SocketException e)
{
System.out.println("Socket already taken, exiting.");
}
catch (Exception ex)
{
Logger.getLogger(Server.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
如果您愿意,我可以提供完整的来源,但我认为这就是所需要的。 同样,Player对象被发送到客户端,客户端接受并将其Player对象设置为接收的对象。我希望客户端的播放器说:“嘿GUI!我刚刚修改过.Lemme调用一个提取/解析我所有数据的更新方法!”
任何帮助都将不胜感激。
更新:
public class ClientListener extends Thread
{
private ObjectInputStream recieving;
public ClientListener(ObjectInputStream in)
{
recieving = in;
}
@Override
public void run()
{
Command cmd;
while(true)
{
try
{
cmd = (Command) recieving.readObject();
clientQ.add(cmd);
java.awt.EventQueue.invokeLater(new Runnable()
{
public void run()
{
try
{
clientQ.take().exec(me);
if(me.changed == true)
updateGUI();
}
catch (Exception ex)
{
Logger.getLogger(ClientGUI.class.getName()).log(Level.SEVERE, null, ex);
}
}
});
}
catch (Exception ex)
{
Logger.getLogger(ClientListener.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
}
似乎它应该是我想要的吗?
答案 0 :(得分:2)
只需将更新代码放入Runnable实例并将其传递给SwingUtilities.InvokeLater()即可。这会将你的runnable放入事件调度队列
或者你可以调用invokeAndWait来阻止,直到更新完成。
如果您尝试调用更新另一个线程中的Swing元素的代码,则可能导致其余代码不稳定。
答案 1 :(得分:2)
使用SwingUtilities.invokeLater在GUI线程中运行处理程序。