Using JFrame from another class

前端 未结 2 607
甜味超标
甜味超标 2020-12-22 06:39

Hi I\'m small a little issue trying to append some text to a JTextArea from another class within the same package. Below is the main class that pertains to the

2条回答
  •  暗喜
    暗喜 (楼主)
    2020-12-22 06:45

    the append function is run nothing appears in the text area of the jFrame

    There's not enough information available in you question to ascertain why this might be happening, how ever, there are a number of important pieces of information you need to take into account.

    1. Swing is single threaded and not thread safe
    2. You want to, as much as possible, decouple of the code

    Basically, the first point means that you shouldn't be running any long running or blocking processes within the Event Dispatching Thread AND you should not be modifying the UI (or any state the UI relies on) from outside the context of the Event Dispatching Thread

    Start by taking a look at Concurrency in Swing for more details.

    The second point means that, for even given part of your code, you want to be asking, "how hard would it be to replace it with some other implementation?" - If the amount of work scares you, then your code is probably to tightly coupled.

    To that end, I started with...

    public interface Client {
        public void append(String message);
    }
    

    This is really basic, but it means that some component can send a message to some other component and neither should care about each other beyond this capability.

    Next, I looked at ServerThread. Basically this class becomes responsible for the management of the Socket and delivery of the messages to the Client. Because of the requirements of Swing, I've used a SwingWorker. This allows me to run the Socket code on a background thread, but ensure that the messages are delivered to the Client within the context of the Event Dispatching Thread

    import java.io.BufferedReader;
    import java.io.IOException;
    import java.io.InputStreamReader;
    import java.net.Socket;
    import java.util.List;
    import javax.swing.SwingWorker;
    
    public class ServerThread extends SwingWorker {
    
        private String host;
        private int port;
        private Client client;
    
        //Constructor
        ServerThread(String host, int port, Client client) {
            this.host = host;
            this.port = port;
            this.client = client;
        }
    
        @Override
        protected void process(List chunks) {
            for (String message : chunks) {
                client.append(message);
            }
        }
    
        @Override
        protected Void doInBackground() throws Exception {
            try (Socket socket = new Socket(host, port)) {
                try (BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream()))) {
                    String text = null;
                    while ((text = reader.readLine()) != null) {
                        System.out.println(text);
                        if (text.equals("")) {
                            break;
                        }
                        publish(text);
                    }
                }
            } catch (IOException exp) {
                exp.printStackTrace();
                publish("Failed to establish connection to " + host + ":" + port + " - " + exp.getMessage());
            }
            return null;
        }
    }
    

    And then the actual UI client itself...

    import java.awt.BorderLayout;
    import java.awt.EventQueue;
    import javax.swing.JFrame;
    import javax.swing.JPanel;
    import javax.swing.JScrollPane;
    import javax.swing.JTextArea;
    
    public class Main {
    
        public static void main(String[] args) {
            new Main();
        }
    
        //Constructor
        public Main() {
            EventQueue.invokeLater(new Runnable() {
                @Override
                public void run() {
                        ClientUI clientUI = new ClientUI();
    
                        ServerThread thread = new ServerThread("localhost", 4321, clientUI);
                        thread.execute();
    
                        JFrame frame = new JFrame("Client");
                        frame.add(clientUI);
                        frame.pack();
                        frame.setLocationRelativeTo(null);
                        frame.setVisible(true);
                }
            });
        }
    
        public class ClientUI extends JPanel implements Client {
    
            private JTextArea ta;
    
            public ClientUI() {
                setLayout(new BorderLayout());
                ta = new JTextArea(10, 20);
                add(new JScrollPane(ta));
            }
    
            @Override
            public void append(String message) {
                ta.append(message + "\n");
            }
    
        }
    }
    

    Not much going on here

    Finally, I wrote a simple Server test the code, which simply sends the current date/time as a String to the connected client.

    When I say simple, I mean simple. This is intended, by design, to tell with a single client connection and is meant only for testing the above code

    import java.io.BufferedWriter;
    import java.io.IOException;
    import java.io.OutputStreamWriter;
    import java.net.ServerSocket;
    import java.net.Socket;
    import java.text.DateFormat;
    import java.util.Date;
    
    public class Server {
    
        public static void main(String[] args) {
            DateFormat format = DateFormat.getDateTimeInstance(DateFormat.LONG, DateFormat.LONG);
            try (ServerSocket server = new ServerSocket(4321)) {
                Socket socket = server.accept();
                System.out.println("Connected");
                try (BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()))) {
                    while (true) {
                        System.out.println("Write >> ");
                        writer.write(format.format(new Date()));
                        writer.newLine();
                        writer.flush();
                        Thread.sleep(1000);
                    }
                }
            } catch (IOException | InterruptedException exp) {
                exp.printStackTrace();
            }
        }
    }
    

    To test it all, start the Server and then run the Main class

提交回复
热议问题