无法附加到 JTextArea
Cant append to JTextArea
我正在尝试与 Java 进行文字聊天。我有一个使用 Streams 相互连接的服务器和一个客户端,并使用 objectInputStream 和 objectOutputStream 发送数据。
我有用于客户端和服务器的 GUI。
我使用 intellij 的 GUI Form 制作了这些 GUI。
server GUI form image
我遇到的问题是当我尝试向服务器的 GUI 显示文本时。如果我从 JTextField 动作侦听器调用我的 relayToAll 方法,我可以附加到 GUI,然后将消息发送到所有客户端并在服务器 GUI 中打印出来。
如果我尝试从我接收输入的地方调用相同的方法,那么附加到文本区域将不起作用。
谁能告诉我为什么不追加?
谢谢
public class ServerTest {
private JTextField textField1;
private JTextArea textArea1;
private JPanel Panel;
static private ObjectOutputStream objectOutputStream;
static private ObjectInputStream objectInputStream;
static private Socket client;
static private ArrayList<Socket> clients = new ArrayList<Socket>();
static private ArrayList<ObjectOutputStream> objectOutputStreams = new ArrayList<>();
public void relayToAll(String message){
try {
for(int i = 0; i < clients.size(); i++) {
ObjectOutputStream output = objectOutputStreams.get(i);
output.writeObject(message);
output.flush();
}
} catch (IOException e) {
e.printStackTrace();
}
appendTextArea(message);
}
public void appendTextArea(String text){
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
System.out.println("This should go to the Server GUI: " + text);
textArea1.append(text + "\n");
}
});
}
public ServerTest() {
textField1.addActionListener(e -> {
System.out.println(e.getActionCommand());
relayToAll(e.getActionCommand());
textField1.setText("");
});
}
public void ReadInput(ObjectInputStream input, int port){
try {
String oldMessage = "";
while (true) {
String message = (String) input.readObject();
if (message != oldMessage){
System.out.println(port + ": " + message);
oldMessage = message;
relayToAll(port + ": " + message);
}
}
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
public void IOSetup(){
try {
ServerSocket serverSocket = new ServerSocket( 6969 );
ExecutorService executor = Executors.newFixedThreadPool(5);
System.out.println("server on\n");
for (int i = 0; i < 5; i++){
client = serverSocket.accept();
clients.add(client);
System.out.println("Connection from: "+ client.getPort());
objectOutputStream = new ObjectOutputStream(client.getOutputStream());
objectOutputStreams.add(objectOutputStream);
objectInputStream = new ObjectInputStream(clients.get(i).getInputStream());
executor.submit(() -> {
ReadInput(objectInputStream, client.getPort());
});
}
} catch (IOException e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
JFrame frame = new JFrame("Server");
frame.setContentPane(new ServerTest().Panel);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setVisible(true);
ServerTest application = new ServerTest();
application.IOSetup();
}
实际上你犯了一个愚蠢的错误。请检查下面的 (A) 和 (B) 行:
public static void main(String[] args) {
JFrame frame = new JFrame("Server");
frame.setContentPane(new ServerTest().Panel); // *************** (A)
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setVisible(true);
ServerTest application = new ServerTest(); // *************** (B)
application.IOSetup();
}
你看到问题了吗?您正在创建 TWO ServerTest 对象,一个将其 Panel 变量添加到 JFrame 并显示,另一个已设置用于IO通信。 ActionListener 更改 displayed JTextArea 的状态,而 IO 通信更改第二个 ServerTest 实例中未显示的 JTextArea 的状态。
一个改进是只创建一个实例:
public static void main(String[] args) {
ServerTest application = new ServerTest(); // create one instance
JFrame frame = new JFrame("Server");
// frame.setContentPane(new ServerTest().Panel);
frame.setContentPane(application.Panel); // and use in both places
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setVisible(true);
//ServerTest application = new ServerTest();
application.IOSetup(); // and use in both places
}
其他问题:
- 你有很长 运行 的代码 运行 并且在后台线程中阻塞,这有潜在的危险,你的 GUI 没有被冻结的唯一原因是因为你在主线程和 Swing 事件线程之外(错误地)启动 GUI。有关更多信息,您需要阅读 Swing 并发性:Lesson: Concurrency in Swing
- 您将想要学习和使用 Java naming conventions。变量名称应全部以小写字母开头,而 class 名称应以大写字母开头。了解并遵循这一点将使我们能够更好地理解您的代码,并使您能够更好地理解其他人的代码。
我正在尝试与 Java 进行文字聊天。我有一个使用 Streams 相互连接的服务器和一个客户端,并使用 objectInputStream 和 objectOutputStream 发送数据。
我有用于客户端和服务器的 GUI。 我使用 intellij 的 GUI Form 制作了这些 GUI。
server GUI form image
我遇到的问题是当我尝试向服务器的 GUI 显示文本时。如果我从 JTextField 动作侦听器调用我的 relayToAll 方法,我可以附加到 GUI,然后将消息发送到所有客户端并在服务器 GUI 中打印出来。
如果我尝试从我接收输入的地方调用相同的方法,那么附加到文本区域将不起作用。
谁能告诉我为什么不追加?
谢谢
public class ServerTest {
private JTextField textField1;
private JTextArea textArea1;
private JPanel Panel;
static private ObjectOutputStream objectOutputStream;
static private ObjectInputStream objectInputStream;
static private Socket client;
static private ArrayList<Socket> clients = new ArrayList<Socket>();
static private ArrayList<ObjectOutputStream> objectOutputStreams = new ArrayList<>();
public void relayToAll(String message){
try {
for(int i = 0; i < clients.size(); i++) {
ObjectOutputStream output = objectOutputStreams.get(i);
output.writeObject(message);
output.flush();
}
} catch (IOException e) {
e.printStackTrace();
}
appendTextArea(message);
}
public void appendTextArea(String text){
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
System.out.println("This should go to the Server GUI: " + text);
textArea1.append(text + "\n");
}
});
}
public ServerTest() {
textField1.addActionListener(e -> {
System.out.println(e.getActionCommand());
relayToAll(e.getActionCommand());
textField1.setText("");
});
}
public void ReadInput(ObjectInputStream input, int port){
try {
String oldMessage = "";
while (true) {
String message = (String) input.readObject();
if (message != oldMessage){
System.out.println(port + ": " + message);
oldMessage = message;
relayToAll(port + ": " + message);
}
}
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
public void IOSetup(){
try {
ServerSocket serverSocket = new ServerSocket( 6969 );
ExecutorService executor = Executors.newFixedThreadPool(5);
System.out.println("server on\n");
for (int i = 0; i < 5; i++){
client = serverSocket.accept();
clients.add(client);
System.out.println("Connection from: "+ client.getPort());
objectOutputStream = new ObjectOutputStream(client.getOutputStream());
objectOutputStreams.add(objectOutputStream);
objectInputStream = new ObjectInputStream(clients.get(i).getInputStream());
executor.submit(() -> {
ReadInput(objectInputStream, client.getPort());
});
}
} catch (IOException e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
JFrame frame = new JFrame("Server");
frame.setContentPane(new ServerTest().Panel);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setVisible(true);
ServerTest application = new ServerTest();
application.IOSetup();
}
实际上你犯了一个愚蠢的错误。请检查下面的 (A) 和 (B) 行:
public static void main(String[] args) {
JFrame frame = new JFrame("Server");
frame.setContentPane(new ServerTest().Panel); // *************** (A)
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setVisible(true);
ServerTest application = new ServerTest(); // *************** (B)
application.IOSetup();
}
你看到问题了吗?您正在创建 TWO ServerTest 对象,一个将其 Panel 变量添加到 JFrame 并显示,另一个已设置用于IO通信。 ActionListener 更改 displayed JTextArea 的状态,而 IO 通信更改第二个 ServerTest 实例中未显示的 JTextArea 的状态。
一个改进是只创建一个实例:
public static void main(String[] args) {
ServerTest application = new ServerTest(); // create one instance
JFrame frame = new JFrame("Server");
// frame.setContentPane(new ServerTest().Panel);
frame.setContentPane(application.Panel); // and use in both places
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setVisible(true);
//ServerTest application = new ServerTest();
application.IOSetup(); // and use in both places
}
其他问题:
- 你有很长 运行 的代码 运行 并且在后台线程中阻塞,这有潜在的危险,你的 GUI 没有被冻结的唯一原因是因为你在主线程和 Swing 事件线程之外(错误地)启动 GUI。有关更多信息,您需要阅读 Swing 并发性:Lesson: Concurrency in Swing
- 您将想要学习和使用 Java naming conventions。变量名称应全部以小写字母开头,而 class 名称应以大写字母开头。了解并遵循这一点将使我们能够更好地理解您的代码,并使您能够更好地理解其他人的代码。