【问题标题】:This code is displaying code on window console but not on the textArea which I had used此代码在窗口控制台上显示代码,但不在我使用的 textArea 上
【发布时间】:2020-09-17 23:55:03
【问题描述】:

下面是我的代码:

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){

                    }
                }
            });    
        }
    }
}

我正在为服务器构建一个窗口,该窗口需要一个连接按钮来连接服务器套接字,但是在为该服务器设置客户端并向客户端发送消息后,该消息显示在 Eclipse 的控制台上,而不是我真正想要成为的文本区域

所以请帮我看看我的代码。

【问题讨论】:

  • 您的while (true) 是从事件侦听器调用的,因此AWT 无法处理任何其他事件:它无法绘制任何内容,也无法响应用户输入。见docs.oracle.com/javase/tutorial/uiswing/concurrency。此外,addActionListener 字面意思是*将一个监听器添加到组件的监听器列表中*——这意味着在循环的第二次迭代之后有两个监听器,下一次有三个监听器,然后是四个,五个,等等。不要在循环中调用addActionListener
  • 嘿...所以请建议我在这里使用的想法。

标签: java swing awt jtextfield jtextarea


【解决方案1】:

两个问题:

  1. 您的 while (true) 循环阻塞了 AWT 事件调度线程。
  2. 您在循环的每次迭代中都添加了一个侦听器。

挂起事件队列

AWT/Swing is single threaded。当您的“连接到服务器”按钮的 ActionListener 被调用时,它会在 AWT 事件调度线程中被调用。在该方法返回之前,不会处理其他事件。

因此,当 ActionListener 调用 getValue() 并且 getValue() 从套接字读取直到遇到 "stop" 时,所有事件处理都将暂停。没有任何东西被重新粉刷。鼠标或键盘输入将没有响应,因为 MouseEvents 和 KeyEvents 没有被处理。

您必须执行 I/O 操作,例如从不同线程上的套接字读取。但是,Swing 方法必须在 AWT 事件调度线程中执行。

一种解决方案是使用SwingWorker 类,其publishprocess 方法允许您将多个数据元素从后台线程发送到AWT 甚至调度线程。

对于发送到套接字,您可以使用线程安全的 BlockingQueue 来存储要发送的行,然后在不同的线程(不是 AWT 事件调度线程)中使用循环从该 BlockingQueue 获取文本并发送它到插座。

只添加一次监听器

addActionListener 方法实际上为按钮添加了一个监听器所有您添加的侦听器将在按下按钮时被调用。

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

您应该只向按钮添加一次 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 {

                // Runs in another thread.
                // No AWT/Swing calls allowed here!

                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) {

                // Runs in event dispatch thread thread.
                // AWT/Swing calls only;  no I/O allowed here!

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

    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();
}

其他一些重要说明:

  • 永远不要写一个空的catch 块。异常告诉你哪里出了问题,哪里出了问题,这是非常有价值的信息。如果您不确定要在 catch 块中添加什么,请写 e.printStackTrace();,以便查看异常的完整详细信息。
  • Learn to use layout managers. 空布局会让您的计算机上看起来不错,但在其他计算机上会出现问题,安装的字体不同并且字体以不同的大小呈现。 (“17 点”表示 ¹⁷⁄₇₂ 英寸,在 120 DPI 监视器上比在 96 DPI 监视器上呈现的像素更多。)此外,空布局意味着您无法调整窗口大小以使 JTextArea 和 JTextField 更大或更小.

【讨论】:

    猜你喜欢
    • 2022-06-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-12-18
    • 2021-02-10
    • 2019-09-04
    • 1970-01-01
    相关资源
    最近更新 更多