Prosty serwer nasłuchujący - problem z GUI

0

Napisałem prosty serwer typu echo z dwoma komponentami: JButton oraz JTextArea. Przycisk ("Server Start") w moim założeniu po naciśnięciu ma zrobić trzy rzeczy: zainicjalizować gniazdo serwera, zablokować się (tzn. sam przycisk a nie całą aplikację ;) ) oraz odblokować obszar tekstowy.

Jako że aplikację będę rozbudowywał oraz dodatkowo chciałbym oddzielić tworzenie GUI od warstwy logicznej aplikacji, główna klasa nie dziedziczy po JFrame. Pliki źródłowe wyglądają następująco:

ServerApplication.java

package gui;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Scanner;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 *
 * @author Krzysztof
 */
public class ServerApplication
{
   public ServerApplication(int width, int height)
   {
      window = new ServerApplicationFrame(sock, PORT, width, height);

      while(sock == null)
      {
         try
         {
            Thread.sleep(100);
         }
         catch (InterruptedException ex)
         {
            Logger.getLogger(ServerApplication.class.getName()).log(Level.SEVERE, null, ex);
         }
      }
      try
      {
         incoming = sock.accept();
         try
         {
            InputStream inStream = incoming.getInputStream();
            OutputStream outStream = incoming.getOutputStream();

            Scanner in = new Scanner(inStream);
            PrintWriter out = new PrintWriter(outStream);

            String line = in.nextLine();
            out.println(line);
         }
         finally
         {
            incoming.close();
         }
      }
      catch(IOException e)
      {
         e.printStackTrace();
      }
   }

   public static void main(String[] args)
   {
      new ServerApplication(250, 250);
   }

   private final ServerApplicationFrame window;
   private ServerSocket sock;
   private Socket incoming;
   private final int PORT = 8800;
}

class NewSocketHelper
{
   public NewSocketHelper(ServerSocket servSocket, int port)
   {
      try
      {
         servSocket = new ServerSocket(port);
      }
      catch(IOException exception)
      {
         exception.printStackTrace();
      }
   }
}

ServerApplicationFrame.java

package gui;

import java.net.ServerSocket;
import javax.swing.JFrame;

class ServerApplicationFrame extends JFrame
{
   public ServerApplicationFrame(ServerSocket servSocket, int port, int width, int height)
   {
      pane = new ServerApplicationPane(servSocket, port);
      FRAME_WIDTH = width;
      FRAME_HEIGHT = height;

      setSize(FRAME_WIDTH, FRAME_HEIGHT);
      setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      setResizable(false);
      setTitle("Server application");

      add(pane);
      setVisible(true);
   }

   private ServerApplicationPane pane;
   private final int FRAME_WIDTH;
   private final int FRAME_HEIGHT;
}

ServerApplicationPane.java

package gui;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.net.ServerSocket;
import javax.swing.JButton;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;

class ServerApplicationPane extends JPanel
{
   public ServerApplicationPane(final ServerSocket servSocket, final int port)
   {
      startServer.addActionListener(new ActionListener()
         {
            public void actionPerformed(ActionEvent e)
            {
               socketConnectHelper = new NewSocketHelper(servSocket, port);
               startServer.setEnabled(false);
               textArea.setEnabled(true);
            }
         });
         textArea.setEditable(false);
         textArea.setEnabled(false);
         addComponents();
   }

   private void addComponents()
   {
      add(new JScrollPane(textArea));
      add(startServer);
   }

   private final JTextArea textArea = new JTextArea("Empty", 9, 20);
   private final JButton startServer = new JButton("Server Start");
   private NewSocketHelper socketConnectHelper;
}

Problem 1. Problem mam teraz następujący (sama aplikacja serwera działa obecnie jak należy). W pierwszym pliku ServerApplication.java dałem pętlę while(sock == null) właśnie po to aby aplikacja nie zaczęła kokoRZystaćystać ze zmiennej serv zanim nie zostanie ona zainicjalizowana obiektem ServSocket, a to następuję dopiero po naciśnięciu przycisku startServer. Takie rozwiązanie mnie się nie podoba bo gdybym chciał (a chcę) dodać jeszcze jeden przycisk np. stopServer to kompletnie zagmatwałoby mi to kod. Wolałbym rozwiązanie z przechwytywaniem stanu przycisku. Czyli coś w stylu, że kod głównej klasy (od wiersza incoming = sock.accept();) jest wykonywany dopiero, gdy przycisk jest zablokowany co byłoby równoważne z tym, że gniazdo serwera zostało już zainicjalizowane.

Problem 2. Nie wiem jak przekazać informację do JTextField że klient dostarczył wiadomość a serwer tą wiadomość odesłał. W tej chwili to mogę co najwyżej taką informację przekazać do konsoli. Pewnie potrzebuję jakiejś referencji w klasie głównej do tego komponentu, i znowu właśnie nie wiem jak to zrobić.

Jak już napisałem we wstępie celowo i świadomie nie chcę aby klasa główna (dotycząca tylko pracy serwera) dziedziczyła po JFrame czy czymkolwiek innym co ma związek z GUI.

Proszę o pomoc i pozdrawiam

0

Problem 2: W klasie glownej uzywasz obiektu JFrame ktorzy ma w sobie instancje obiektu JPanel ktory z kolei ma w sobie instancje obiektu JTextArea. Tak wiec wystarczy po prostu napisac w klasie ServerApplicationPane metode cos ala:

   setTextArea(String s){
      textArea.setText(s);
   }

W klasie ServerApplicationFrame

   setTextArea(String s){
      pane.setTextArea(s);
   }

I w klasie glownej za pomoca metody window.setTextArea("nowy tekst); zmieniasz sobie wartosc tego komponentu.

1 użytkowników online, w tym zalogowanych: 0, gości: 1