java - 无法附加到 JTextArea
问题描述
我正在尝试使用 Java 创建文本聊天。我有一个服务器和一个客户端,它们使用 Streams 相互连接,并使用 objectInputStream 和 objectOutputStream 发送数据。
我有客户端和服务器的 GUI。我使用 intellij 的 GUI 表单制作了这些 GUI。
我遇到的问题是当我尝试向服务器的 GUI 显示文本时。如果我从 JTextField actionlistener 调用我的 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();
}
你看到问题了吗?您正在创建两个ServerTest 对象,一个将其 Panel 变量添加到 JFrame 并显示,另一个设置用于 IO 通信。ActionListener 更改显示的 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 没有被冻结的唯一原因是因为您在主线程上(错误地)启动了 GUI,并且脱离 Swing 事件线程。有关这方面的更多信息,您需要阅读 Swing 并发:课程:Swing 中的并发
- 您将想要学习和使用Java 命名约定。变量名应全部以小写字母开头,而类名应以大写字母开头。学习这一点并遵循这一点将使我们更好地理解您的代码,并使您更好地理解其他人的代码。
推荐阅读
- reactjs - react native:“无法对未安装的组件执行 React 状态更新”useContext 问题
- python - 在 Pandas 中使用 groupby、shift 和 rolling
- unity3d - “图像”不包含 Unity 上“颜色”的定义
- jupyter-notebook - 有没有办法在集群上为 .ipynb 文件提交 Google Dataproc PySpark 作业?
- python - 计算来自 pandas groupby 的匹配值的数量
- c++ - MOVNTI 存储是否相对于同一线程创建的其他 MOVNTI 存储重新排序?
- f# - F# pattern matching with optional list of tuples
- c# - 声明 C# 构造函数时大括号不匹配
- dart - 更改检查映射键是否相等的方式
- reactjs - 如何将参数传递给历史推送