我举了一个例子,说明我希望我的程序是什么。问题是我无法使我的套接字连接正常工作(我希望它的工作方式)。我不知道问题出在哪里。
public class TestChat extends Frame {
public static Panel1 p1;
public static Panel2 p2;
public static TestChat tc;
public TestChat() {
super();
setPreferredSize(new Dimension(800, 600));
setLayout(new BorderLayout());
addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent we) {
System.exit(0);
}
});
p1 = new Panel1();
p2 = new Panel2();
add(p1);
}
public static void main(String[] args) {
// TODO code application logic here
tc = new TestChat();
tc.pack();
tc.setVisible(true);
///*
try {
TestChat.p2.run();
} catch (IOException ioe) {
System.out.println("IO here");
}
//*/
}
public void change(int to) {
if (to == 1) {
tc.remove(p2);
tc.add(p1);
}
if (to == 2) {
tc.remove(p1);
tc.add(p2);
}
tc.pack();
}
}
public class Panel1 extends Panel implements ActionListener{
public Button button = new Button("Launch chat");
public Panel1() {
super();
setLayout(new BorderLayout());
Label label = new Label("Launcher panel here");
add(label);
add(button, BorderLayout.SOUTH);
button.addActionListener(this);
}
@Override
public void actionPerformed(ActionEvent e) {
if (e.getSource() == button) {
TestChat.tc.change(2);
/*
try {
TestChat.p2.run();
} catch (IOException ioe) {
System.out.println("IO here");
}
//*/
}
}
}
public class Panel2 extends Panel implements ActionListener {
private static final int LOGIN_MAX = 300;
public static TextArea ta = new TextArea();
public static TextField tf = new TextField();
public static TextArea logins = new TextArea();
public static PrintWriter out = null;
public static String[] loginList = new String[LOGIN_MAX];
public static int loginCount = 0;
public Panel temp = new Panel();
public Button startButton = new Button("Start!");
///*
public String fromServer;
public BufferedReader in = null;
public BufferedReader stdIn;
public Socket kkSocket = null;
//*/
public Panel2() {
setLayout(new BorderLayout());
temp.setLayout(new BorderLayout());
ta.setEditable(false);
tf.addActionListener(this);
startButton.addActionListener(this);
logins.setEditable(false);
temp.add(ta, BorderLayout.CENTER);
temp.add(tf, BorderLayout.SOUTH);
add(temp);
add(logins, BorderLayout.EAST);
add(startButton, BorderLayout.SOUTH);
}
//private static void makeLogins() {
public static void makeLogins() {
String userArea = loginList[0] + "\n";
for (int i = 1; i < loginCount; i++) {
userArea = userArea + loginList[i] + "\n";
}
logins.setText(userArea);
}
public void run() throws IOException {
kkSocket = null;
BufferedReader in = null;
try {
kkSocket = new Socket("localhost", 4444);
out = new PrintWriter(kkSocket.getOutputStream(), true);
in = new BufferedReader(new InputStreamReader(kkSocket.getInputStream()));
} catch (UnknownHostException e) {
//System.err.println("Can't host to server.");
System.out.println("Can't host to server.");
System.exit(1);
} catch (IOException e) {
System.err.println("Couldn't get I/O for the connection to server.");
System.exit(1);
}
BufferedReader stdIn = new BufferedReader(new InputStreamReader(System.in));
String fromServer;
while ((fromServer = in.readLine()) != null) {
validate();
if (fromServer.startsWith("cmd_newUser_")) {
loginList[loginCount++] = fromServer.substring(12);
if (loginCount > 1) {
Arrays.sort(loginList, 1, loginCount - 1);
}
makeLogins();
} else if (fromServer.startsWith("cmd_deleteUser_")) {
String tmp = fromServer.substring(15);
for (int i = 0; i < loginCount; i++) {
if (loginList[i].equals(tmp)) {
loginList[i] = "" + ((char) 255);
break;
}
}
Arrays.sort(loginList, 1, loginCount);
loginCount--;
makeLogins();
} else {
ta.append(fromServer + "\n");
}
if (fromServer.equals("Bye.")) {
break;
}
}
out.close();
in.close();
stdIn.close();
}
private void sendStr(PrintWriter out) {
if (tf.getText() != "") {
out.println(tf.getText());
tf.setText("");
}
}
@Override
public void actionPerformed(ActionEvent e) {
if (e.getSource() == tf) {
sendStr(out);
} else if (e.getSource() == startButton) {
System.out.println("I make some actions in the original proj");
}
}
}
当我以这种方式使用它时,我的程序连接,一切正常。但是我想在按下按钮时从Panel1类开始连接(注释调用)。当我尝试从Panel1调用它时,我的整个程序冻结了。这里的问题在哪里,我该如何解决?
P.S。这是我的服务器代码(以防万一)
public class KKMultiServer extends Frame {
public static int userCount = 0;
public static Label users;
public static KKMultiServerThread[] userList=new KKMultiServerThread[100];
public static int writer=0;
public static int curNum=1;
public KKMultiServer() {
super("Server");
setLayout(new GridLayout(2, 1));
users = new Label("Users online: " + userCount);
add(users);
setLocation(200, 200);
setResizable(false);
setMinimumSize(new Dimension(300, 200));
addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent we) {
System.exit(0);
}
});
}
public static void main(String[] args) throws IOException {
ServerSocket serverSocket = null;
boolean listening = true;
KKMultiServer server = new KKMultiServer();
server.pack();
server.setVisible(true);
try {
serverSocket = new ServerSocket(4444);
} catch (IOException e) {
System.err.println("Could not listen on port: 4444.");
System.exit(-1);
}
while (listening) {
userList[writer]=new KKMultiServerThread(serverSocket.accept());
System.out.println("Client added!");
userCount++;
users.setText("Users online: " + userCount);
userList[writer++].start();
}
serverSocket.close();
}
}
答案 0 :(得分:1)
static
引用是一个非常糟糕的设计。您冒着不确切知道引用内容的风险。到目前为止,你已经基本上把它搞砸了。当{J}运行main
时,它正在运行,通常称为“主”线程。当您开始使用任何Swing组件时,Swing API将启动“事件调度线程”...
所以发生了什么,你正在启动你的应用程序的UI部分,它的上下文正在转移到EDT,而run
方法p2
继续在{{1}中运行} thread。
现在您想要从按钮启动通信,您已将执行上下文移动到EDT,这使得它看起来像应用程序已挂起....
现在,你有两个问题。首先,你需要将你的通信从EDT中删除,你的第二个是,你不应该从EDT以外的任何线程修改或更新UI ...
您可以使用多种解决方案,main
可能是最简单的问题。
请查看Concurrency in Swing了解详情