这段代码在窗口控制台上显示代码,但未在我所使用的文本区域中显示。

huangapple go评论63阅读模式
英文:

This code is displaying code on window console but not on the textArea which I had used

问题

以下是您的代码的翻译部分:

package Project1;

import java.awt.BorderLayout;
import java.awt.EventQueue;

import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.border.EmptyBorder;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.JButton;
import java.awt.Font;
import javax.swing.JScrollBar;
import java.awt.Color;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;

public class DonorChat extends JFrame {
    /**
     * 
     */
    private static final long serialVersionUID = 1L;
    String get = null;
    String s1 = null;
    DataOutputStream dos;
    DataInputStream dis;
    JButton btnNewButton;
    private JPanel contentPane;
    public JTextField textField;
    public JTextArea textArea;
    public JButton btnNewButton_1;

    public DonorChat() {
        setTitle("Donor Chat");
        setIconImage(Toolkit.getDefaultToolkit().getImage("E:\\algorithm\\Project1\\Project1\\Blood.png"));
        setForeground(Color.RED);
        setFont(null);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setBounds(0, 0, 800, 1000);
        contentPane = new JPanel();
        contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
        setContentPane(contentPane);
        contentPane.setLayout(null);

        textArea = new JTextArea();
        textArea.setFont(new Font("Tahoma", Font.BOLD, 17));
        textArea.setBounds(31, 222, 707, 522);
        contentPane.add(textArea);

        textField = new JTextField();
        textField.setFont(new Font("Tahoma", Font.BOLD, 17));
        textField.setBounds(31, 793, 510, 105);
        contentPane.add(textField);
        textField.setColumns(10);
        textField.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent arg0) {
                // TODO Auto-generated method stub
            }
        });

        btnNewButton = new JButton("Send");
        btnNewButton.setFont(new Font("Tahoma", Font.BOLD, 17));
        btnNewButton.setForeground(Color.RED);
        btnNewButton.setBackground(Color.LIGHT_GRAY);
        btnNewButton.setBounds(602, 820, 125, 47);
        contentPane.add(btnNewButton);

        JScrollBar scrollBar = new JScrollBar();
        scrollBar.setBounds(717, 222, 21, 522);
        contentPane.add(scrollBar);

        btnNewButton_1 = new JButton("CONNECT TO SERVER");
        btnNewButton_1.setBackground(Color.RED);
        btnNewButton_1.setForeground(Color.DARK_GRAY);
        btnNewButton_1.setFont(new Font("Times New Roman", Font.BOLD, 29));
        btnNewButton_1.setBounds(31, 60, 707, 86);
        contentPane.add(btnNewButton_1);
        btnNewButton_1.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent arg0) {
                // TODO Auto-generated method stub
                try {
                    ServerSocket ss = new ServerSocket(9995);
                    Socket snSocket = ss.accept();
                    dos = new DataOutputStream(snSocket.getOutputStream());
                    dis = new DataInputStream(snSocket.getInputStream());
                    getValue();
                    ss.close();
                } catch (IOException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
        });

        setVisible(true);
    }

    public void getValue() throws IOException {
        btnNewButton.removeActionListener(null);
        while (true) {
            s1 = dis.readUTF();
            if (s1.equals("stop")) {
                textArea.setText("Client Want to Stop:" + s1);
                break;
            } else {
                System.out.println("Client Says:" + s1);
                textArea.setText("Client Says:" + s1);
            }
            System.out.println("Type Something for Client");
            btnNewButton.addActionListener(new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent arg0) {
                    try {
                        dos.writeUTF(get);
                    } catch (Exception e) {

                    }
                }
            });
        }
    }
}

如果您需要更多的帮助或解释,请随时提问。

英文:

Below is my code:

package Project1;
import java.awt.BorderLayout;
import java.awt.EventQueue;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.border.EmptyBorder;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.JButton;
import java.awt.Font;
import javax.swing.JScrollBar;
import java.awt.Color;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
public class DonorChat extends JFrame {
/**
* 
*/
private static final long serialVersionUID = 1L;
String get=null;
String s1=null;
DataOutputStream dos;
DataInputStream dis;
JButton btnNewButton;
private JPanel contentPane;
public JTextField textField;
public JTextArea textArea ;
public JButton btnNewButton_1;
public DonorChat() {
setTitle("Donor Chat");
//        setIconImage(Toolkit.getDefaultToolkit().getImage("E:\\algorithm\\Project1\\Project1\\Blood.png"));
setIconImage(Toolkit.getDefaultToolkit().getImage("E:\\algorithm\\Project1\\Project1\\Blood.png"));
setForeground(Color.RED);
setFont(null);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setBounds(0, 0, 800, 1000);
contentPane = new JPanel();
contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
setContentPane(contentPane);
contentPane.setLayout(null);
textArea= new JTextArea();
textArea.setFont(new Font("Tahoma", Font.BOLD, 17));
textArea.setBounds(31, 222, 707, 522);
contentPane.add(textArea);
textField = new JTextField();
textField.setFont(new Font("Tahoma", Font.BOLD, 17));
textField.setBounds(31, 793, 510, 105);
contentPane.add(textField);
textField.setColumns(10);
textField.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent arg0) {
// TODO Auto-generated method stub
}
});
btnNewButton = new JButton("Send\r\n");
btnNewButton.setFont(new Font("Tahoma", Font.BOLD, 17));
btnNewButton.setForeground(Color.RED);
btnNewButton.setBackground(Color.LIGHT_GRAY);
btnNewButton.setBounds(602, 820, 125, 47);
contentPane.add(btnNewButton);
JScrollBar scrollBar = new JScrollBar();
scrollBar.setBounds(717, 222, 21, 522);
contentPane.add(scrollBar);
btnNewButton_1 = new JButton("CONNECT TO SERVER");
btnNewButton_1.setBackground(Color.RED);
btnNewButton_1.setForeground(Color.DARK_GRAY);
btnNewButton_1.setFont(new Font("Times New Roman", Font.BOLD, 29));
btnNewButton_1.setBounds(31, 60, 707, 86);
contentPane.add(btnNewButton_1);
btnNewButton_1.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent arg0) {
// TODO Auto-generated method stub
try {
ServerSocket ss=new ServerSocket(9995);
Socket snSocket=ss.accept();
dos=new DataOutputStream(snSocket.getOutputStream());
dis=new DataInputStream(snSocket.getInputStream());
getValue();
ss.close();
} 
catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
});
setVisible(true);
}
public void getValue() throws IOException{
btnNewButton.removeActionListener(null);
while(true){
s1=dis.readUTF();
if (s1.equals("stop")){
textArea.setText("Client Want to Stop:"+s1);
break;
}
else{
System.out.println("Client Says:"+s1);
textArea.setText("Client Says:"+s1);
}
System.out.println("Type Something for Client");
btnNewButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent arg0){
try {
dos.writeUTF(get);
}
catch(Exception e){
}
}
});    
}
}
}

I am building a window for server which needs a connection button to connect with the server socket, but after setting up the client for that server and after sending client a message, the message is showing on the console for eclipse but not on the textarea which what I actually wants to be

So please help me out by having a look at my code.

答案1

得分: 1

两个问题:

  1. 你的 while (true) 循环正在阻塞 AWT 事件分发线程。
  2. 你在每次循环迭代中都在添加一个监听器。

阻塞事件队列

AWT/Swing 是单线程的。当你的“连接到服务器”按钮的 ActionListener 被调用时,它是在 AWT 事件分发线程中被调用的。在该方法返回之前,不会处理任何其他事件。

因此,当 ActionListener 调用 getValue() 时,而 getValue() 从 socket 中读取直到遇到 "stop" 为止,所有事件的处理都会暂停。没有任何重绘。鼠标或键盘输入没有响应,因为 MouseEvents 和 KeyEvents 不会被处理。

你必须在不同的线程上执行像从 socket 中读取这样的 I/O 操作。然而,Swing 方法必须在 AWT 事件分发线程中执行。

一个解决方案是使用 SwingWorker 类,其 publishprocess 方法允许你从后台线程向 AWT 事件分发线程发送多个数据元素。

对于发送到 socket,你可以使用线程安全的 BlockingQueue 来存储要发送的行,然后在不同的线程中(不是 AWT 事件分发线程)使用循环从该 BlockingQueue 获取文本并将其发送到 socket。

仅添加一次监听器

方法 addActionListener 实际上是向按钮添加侦听器。当按钮被按下时,所有你添加的侦听器都将被调用。

因此,如果你在每次循环执行时调用 addActionListener,你将为从 socket 中读取的每个数据添加一个侦听器!

你应该只在按钮上添加一次 ActionListener,通常是在创建按钮后立即执行。

代码

因此,如果我们将 I/O 移动到其他线程,并使用 BlockingQueue 来跟踪要发送的行,代码看起来可能是这样的:

private final BlockingQueue<String> linesToSend =
    new LinkedBlockingDeque<>();

public DonorChat() {

    // ...

    textField.addActionListener(new ActionListener() {
        linesToSend.add(textField.getText());
    });

    btnNewButton.addActionListener(new ActionListener() {
        linesToSend.add(textField.getText());
    });

    // ...
}

private void getValue(Socket snSocket) {

    textArea.setText("");

    SwingWorker<Void, String> socketReader =
        new SwingWorker<Void, String>() {
            @Override
            protected Void doInBackground()
            throws IOException {

                // 在另一个线程中运行。
                // 这里不允许有 AWT/Swing 调用!

                dis = new DataInputStream(snSocket.getInputStream());

                while (true) {
                    String s1 = dis.readUTF();
                    if (s1.equals("stop")) {
                        publish("Client wants to stop.");
                        break;
                    }

                    publish("Client says: " + s1);
                }

                snSocket.close();

                return null;
            }

            @Override
            protected void process(List<String> linesRead) {

                // 在事件分发线程中运行。
                // 只允许 AWT/Swing 调用;这里不允许 I/O!

                for (String line : linesRead) {
                    textArea.append(line + "\n");
                }
            }
        };

    socketReader.execute();

    // 要发送的行是在 AWT 事件分发线程中添加的
    // 由 ActionListeners。
    // 我们希望在不同的线程中将它们发送到 socket。

    Runnable linesSender = new Runnable() {
        @Override
        public void run() {
            try {
                dos = new DataOutputStream(snSocket.getOutputStream());
                while (true) {
                    dos.writeUTF(linesToSend.take());
                }
            } catch (IOException | InterruptedException e) {
                e.printStackTrace();
            }
        }
    };

    new Thread(linesSender).start();
}

其他重要注意事项:

  • 永远不要写一个空的 catch 块。异常会告诉你发生了什么错误以及在哪里,这是非常有价值的信息。如果不确定在 catch 块中要放什么,写上 e.printStackTrace(); 以便查看完整的异常详情。
  • 学会使用布局管理器。使用空布局可能在你的计算机上看起来还好,但在其他计算机上会出现问题,因为安装的字体不同,字体以不同的大小呈现。(“17 points” 意味着 ¹⁷⁄₇₂ 英寸,在 120 DPI 显示器上比 96 DPI 显示器上渲染更多的像素。)此外,空布局意味着你无法调整窗口大小,以使 JTextArea 和 JTextField 变大或变小。
英文:

Two problems:

  1. Your while (true) loop is blocking the AWT event dispatch thread.
  2. You are adding a listener in every iteration of your loop.

Holding up the event queue

AWT/Swing is single threaded. When your “CONNECT TO SERVER” button’s ActionListener is called, it is called in the AWT event dispatch thread. No other events will be processed until that method returns.

So when that ActionListener calls getValue(), and getValue() reads from a socket until &quot;stop&quot; is encountered, all processing of events is suspended. Nothing gets repainted. There will be no response to mouse or keyboard input, because the MouseEvents and KeyEvents are not processed.

You must perform I/O operations like reading from a socket on a different thread. However, Swing methods must be executed in the AWT event dispatch thread.

One solution is to use the SwingWorker class, whose publish and process methods allow you to send multiple data elements from a background thread to the AWT even dispatch thread.

For sending to the socket, you can use a thread-safe BlockingQueue to store the lines to send, then use a loop in a different thread (not the AWT event dispatch thread) to obtain the text from that BlockingQueue and send it to the socket.

Add a listener only once

The method addActionListener actually adds a listener to a button. All of the listeners you add will be called when the button is pressed.

So, if you call addActionListener every time your loop executes, you will have added a listener for each piece of data you read from the socket!

You should only add an ActionListener to a button once—usually right after you have created the button.

Code

So, if we move the I/O to other threads and use a BlockingQueue to keep track of lines to send, it looks something like this:

private final BlockingQueue&lt;String&gt; linesToSend =
new LinkedBlockingDeque&lt;&gt;();
public DonorChat() {
// ...
textField.addActionListener(new ActionListener() {
linesToSend.add(textField.getText());
});
btnNewButton.addActionListener(new ActionListener() {
linesToSend.add(textField.getText());
});
// ...
}
private void getValue(Socket snSocket) {
textArea.setText(&quot;&quot;);
SwingWorker&lt;Void, String&gt; socketReader =
new SwingWorker&lt;Void, String&gt;() {
@Override
protected Void doInBackground()
throws IOException {
// Runs in another thread.
// No AWT/Swing calls allowed here!
dis = new DataInputStream(snSocket.getInputStream());
while (true) {
String s1 = dis.readUTF();
if (s1.equals(&quot;stop&quot;)) {
publish(&quot;Client wants to stop.&quot;);
break;
}
publish(&quot;Client says: &quot; + s1);
}
snSocket.close();
return null;
}
@Override
protected void process(List&lt;String&gt; linesRead) {
// Runs in event dispatch thread thread.
// AWT/Swing calls only;  no I/O allowed here!
for (String line : linesRead) {
textArea.append(line + &quot;\n&quot;);
}
}
};
socketReader.execute();
// Lines to send were added in AWT event dispatch thread
// by ActionListeners.
// We want to send them to the socket in a different thread.
Runnable linesSender = new Runnable() {
@Override
public void run() {
try {
dos = new DataOutputStream(snSocket.getOutputStream());
while (true) {
dos.writeUTF(linesToSend.take());
}
} catch (IOException | InterruptedException e) {
e.printStackTrace();
}
}
};
new Thread(linesSender).start();
}

Some other important notes:

  • Never write an empty catch block. Exceptions tell you what went wrong and where, which is very valuable information. If you’re not sure what to put in a catch block, write e.printStackTrace(); so you can see the full details of the exception.
  • Learn to use layout managers. A null layout will make things look okay on your computer, but will have problems on other computers, where the installed fonts are different and the fonts are rendered at different sizes. (“17 points” means ¹⁷⁄₇₂ inch, which is rendered with more pixels on a 120 DPI monitor than on a 96 DPI monitor.) Also, a null layout means you cannot resize the window to make the JTextArea and JTextField larger or smaller.

huangapple
  • 本文由 发表于 2020年5月30日 20:28:42
  • 转载请务必保留本文链接:https://go.coder-hub.com/62102450.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定