gpt4 book ai didi

java - 无法更新 Swing 中的文本区域

转载 作者:行者123 更新时间:2023-11-30 06:10:18 25 4
gpt4 key购买 nike

这是我在 StackOverflow 上的第一个问题,所以我希望我的问题不会太模糊或格式错误。

我正在尝试使用 Netbeans Swing GUI 生成器在 Java 中构建一个桌面聊天应用程序,并在 Swing 中构建 GUI。有一台服务器托管聊天,而多个客户端可以连接和离开聊天。对于连接到服务器的每个客户端,我创建一个新线程来处理与相应客户端的所有通信。当客户端发送消息时,它首先转到服务器,其中有一个线程读取该消息,更新聊天日志(文本区域),然后通过调用 write() 将消息写入所有其他客户端。

以下是服务器代码:

import java.io.*;
import java.net.*;

public class server extends javax.swing.JFrame implements Runnable
{

static Socket sock[]=new Socket[100]; //Array of sockets, 1 for each accept
static server obj[]=new server[100]; //Array of server objects, 1 for each thread
static Thread threads[]=new Thread[100]; //Array of threads, 1 for each client
static boolean conn_state[]=new boolean[100]; //Array of boolean values depicting whether connection is closed or not
static DataOutputStream dos[]=new DataOutputStream[100]; //Array of DataOutputStreams, 1 for each client
static InetAddress ipaddr[]=new InetAddress[100]; //Array to hold InetAddress objects of each client
static int port[]=new int[100]; //Array to hold port numbers
static int i=0; //No. of clients
static int except=0; //Marks client no. who sent last message
static int count=0; //Total no. of open connections at any time
static boolean flag=false; //Currently unused
static String str; //To hold message sent by a client
public server() {
initComponents();
setLocationRelativeTo(null);
}

/**
* 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() {

jLabel1 = new javax.swing.JLabel();
jButton1 = new javax.swing.JButton();
jButton2 = new javax.swing.JButton();
jScrollPane1 = new javax.swing.JScrollPane();
jTextArea1 = new javax.swing.JTextArea();

setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
setResizable(false);

jLabel1.setText("Chat Log :");

jButton1.setBackground(new java.awt.Color(204, 204, 255));
jButton1.setText("Stop Server");
jButton1.setToolTipText("Stop the server hosting the chat.");
jButton1.setPreferredSize(new java.awt.Dimension(120, 25));

jButton2.setText("Print Chat Log");
jButton2.setPreferredSize(new java.awt.Dimension(120, 25));

jScrollPane1.setAutoscrolls(true);

jTextArea1.setColumns(20);
jTextArea1.setRows(5);
jScrollPane1.setViewportView(jTextArea1);

javax.swing.GroupLayout layout = new
javax.swing.GroupLayout(getContentPane());
getContentPane().setLayout(layout);
layout.setHorizontalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addGap(52, 52, 52)
.addComponent(jButton1, javax.swing.GroupLayout.PREFERRED_SIZE, 120, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addComponent(jButton2, javax.swing.GroupLayout.PREFERRED_SIZE, 120, javax.swing.GroupLayout.PREFERRED_SIZE)
.addGap(52, 52, 52))
.addGroup(layout.createSequentialGroup()
.addGap(22, 22, 22)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, 356, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(jLabel1, javax.swing.GroupLayout.PREFERRED_SIZE, 118, javax.swing.GroupLayout.PREFERRED_SIZE))
.addContainerGap(22, Short.MAX_VALUE))
);
layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addContainerGap()
.addComponent(jLabel1, javax.swing.GroupLayout.PREFERRED_SIZE, 25, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addComponent(jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, 179, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 34, Short.MAX_VALUE)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(jButton1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(jButton2, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
.addGap(34, 34, 34))
);

pack();
}// </editor-fold>

public static void serve()
{
System.out.println("Server Program Running");
try
{
ServerSocket ss =new ServerSocket(50000);
while(true)
{
sock[i]=ss.accept();
System.out.println("Client with IP Address :- "+sock[i].getInetAddress().getHostAddress()+":"+sock[i].getPort()+" connected.");
obj[i]=new server();
threads[i]=new Thread(obj[i]);
conn_state[i]=true;
dos[i]=new DataOutputStream(sock[i].getOutputStream());
ipaddr[i]=sock[i].getInetAddress();
port[i]=sock[i].getPort();
count++;
i++;
threads[i-1].start(); //A new thread is created for each client to read all incoming messages and write it out to every other client
}
}
catch(Exception e)
{
System.out.println(e.getMessage());
}
}
@Override
public void run()
{
try
{
int k=i-1; //Marks client no.

//TextArea does not get updated by the following lines
jTextArea1.append("Client with IP Address :- "+sock[k].getInetAddress().getHostAddress()+":"+sock[k].getPort()+" connected.");
jTextArea1.update(jTextArea1.getGraphics());

DataInputStream dis = new DataInputStream(sock[k].getInputStream());
while(true)
{
//System.out.println("k="+k);
str=dis.readUTF();
if(str.equalsIgnoreCase("exit"))
{
//If a client types exit, the server closes all socket and streams of that client and writes out thst the client has left
dis.close();
conn_state[k]=false;
sock[k].close();
count--;
str="Client with ip ="+(ipaddr[k].getHostAddress())+" and port no. = "+port[k]+" left the chat.";
flag=true;
write();
if(count!=0) //When open connections = 0, the server shuts down
return;
else
System.exit(0);
}
except=k;
str=ipaddr[k].getHostAddress()+":"+port[k]+" :- "+str;
System.out.println(str);

//The text area does not get updated
jTextArea1.setText(jTextArea1.getText()+str);
jTextArea1.repaint();

write(); //Function to write out "str" to all other clients
}
}
catch(Exception e)
{
e.printStackTrace();
}
}
public void write()
{
int c;
for(c=0;c<i;c++)
{
//System.out.println(c);
if(c==except||conn_state[c]==false) //If c=current sender's client no. or connection is closed then do not write to it
continue;
try
{
/*if(!flag)
str="From IP Address :- "+ipaddr[except].getHostAddress()+":"+port[except]+"\nMessage : "+str;*/
dos[c].writeUTF(str); //Writing "str" to every client other than except
dos[c].flush();
//dos.close();
}
catch(Exception e)
{
e.printStackTrace();
}
}
}
/**
* @param args the command line arguments
*/
public static void main(String args[]) {
/* Set the Nimbus look and feel */
//<editor-fold defaultstate="collapsed" desc=" Look and feel setting code (optional) ">
/* If Nimbus (introduced in Java SE 6) is not available, stay with the default look and feel.
* For details see
http://download.oracle.com/javase/tutorial/uiswing/lookandfeel/plaf.html
*/
try {
for (javax.swing.UIManager.LookAndFeelInfo info : javax.swing.UIManager.getInstalledLookAndFeels()) {
if ("Nimbus".equals(info.getName())) {
javax.swing.UIManager.setLookAndFeel(info.getClassName());
break;
}
}
} catch (ClassNotFoundException ex) {
java.util.logging.Logger.getLogger(server.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
} catch (InstantiationException ex) {
java.util.logging.Logger.getLogger(server.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
} catch (IllegalAccessException ex) {
java.util.logging.Logger.getLogger(server.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
} catch (javax.swing.UnsupportedLookAndFeelException ex) {
java.util.logging.Logger.getLogger(server.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
}
//</editor-fold>

/* Create and display the form */
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
new server().setVisible(true);
}
});
serve(); //Main job done by server
}

// Variables declaration - do not modify
private javax.swing.JButton jButton1;
private javax.swing.JButton jButton2;
private javax.swing.JLabel jLabel1;
private javax.swing.JScrollPane jScrollPane1;
private javax.swing.JTextArea jTextArea1;
// End of variables declaration

}

现在,当我作为客户端连接到服务器时,“客户端已连接”消息和客户端发送的所有消息都正确输出到控制台,但文本区域中没有显示任何内容。客户端代码仅包含连接到服务器,然后运行 ​​2 个线程,一个用于读取,一个用于写入。

当我用 C 实现这么多客户端-服务器模型时,没有任何 GUI,它工作得很好。当所有输出都打印到控制台而不是 GUI 上时,我什至设法在 Java 中完成相同的工作。当我尝试包含 GUI 时,GUI 上什么也没有显示。谷歌搜索我的问题导致了 StackOverflow 上的问题,从中我了解到 Swing 组件只能由 1 个名为 EDT 的线程更改,并且没有其他线程可以更改它们。他们建议使用

SwingUtilities.InvokeLater(new Runnable() {
public void run() {
JTextArea1.setText(jTextArea1.getText()+str);
}
});

但是我已经尝试过了,还是不行。

如果您愿意调查此事,我将不胜感激。如果代码过于聚集、不干净或充满不良做法,我感到非常抱歉。我对编码还是新手,对 Java 还比较陌生,欢迎提供任何反馈。

最佳答案

抱歉,我的第一次分析不完整。

您看到的 JFrame 是在 main 方法中创建的。然而,没有线程向它的文本区域写入任何内容,因为您没有保留对框架或文本区域的引用。

您创建的每个进一步的server实例都将在JFrameJTextArea上创建它,但这些永远不会显示在屏幕上(您永远不会在这些帧上调用 setVisible(true);)。

为了解决您的问题,最好创建两个类:

  • 一个用于与客户端通信的类(可以为每个连接的客户端创建此类的实例,可以将其称为ServerCommunication)
  • 一个用于应用程序的 GUI(您将只有该类的一个实例,并将对其的引用传递给每个通信类实例,也许可以将此称为 ServerGUI)
<小时/>

更新文本区域的正确方法是来自您提供的片段:

SwingUtilities.invokeLater(new Runnable() {
public void run() {
jTextArea1.setText(jTextArea1.getText()+str);
}
});

或者,使用 Java 8 及更高版本中的 lambda:

SwingUtilities.invokeLater(() -> {
jTextArea1.setText(jTextArea1.getText()+str);
});

请不要尝试调用 jTextArea1.repaint();jTextArea1.update(jTextArea1.getGraphics()); - 在这种情况下,这些调用是无意义的完全没有必要。

关于java - 无法更新 Swing 中的文本区域,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50397355/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com