So, I've been making a gui for a client to connect to a server using it. What I want is when I press Login to connect with the specfied Server address and port name on the gui. If I have hardcoded the Server and port it works but I don't want it like that ... I want to be able to switch the server address and port on the go. Any ideas? I tried rearranging the code and what I get is everytime I click Login now it creates a new GUI. So basically I see the problem on this line
finalClient fc = new finalClient(defaultHost,defaultPort);
where I need the object of the class to be able to use run(); but ofc it creates new gui every time, and what I want to do is use the one created by default when lauching .. Here is the entire code:(omitting the implementation besides the GUI as its vector clocks n stuff)

class finalClient
{   
    private String sentence;
    private String modifiedSentence;
    private JFrame frame = new JFrame("Distributed Systems project");
    private JTextField textField = new JTextField(40);
    private JTextArea messageArea = new JTextArea(30, 40);
    private DataOutputStream outToServer;
    private PrintWriter out;
    private int defaultPort;
    private String defaultHost;
    private JTextField tfServer, tfPort;
    private JLabel label;
    private JButton login, logout;
    private Boolean connected;
    private int msgNumber;
    private Pattern msgre = Pattern.compile("\\[(.*?)\\] \\((.*)\\)"); //Regular expression for the vector clocks
    private Pattern vclock = Pattern.compile("\\((\\d+),(\\d+)\\)"); // regular expression for the numbers of the vector clocks
    private HashMap<Long, Long> lastClock = new HashMap<Long,Long>();
    private ArrayList<Message> received = new ArrayList<Message>();


    public finalClient(String host, int port) {
        defaultHost = host;
        defaultPort = port;

        // Layout GUI
        textField.setEditable(true);
        messageArea.setEditable(false);

        // The NorthPanel with:
        JPanel northPanel = new JPanel(new GridLayout(3,1));
        // the server name anmd the port number
        JPanel serverAndPort = new JPanel(new GridLayout(1,5, 1, 3));
        // the two JTextField with default value for server address and port number
        tfServer = new JTextField(host);
        tfPort = new JTextField("" + port);
        tfPort.setHorizontalAlignment(SwingConstants.RIGHT);

        serverAndPort.add(new JLabel("Server Address:  "));
        serverAndPort.add(tfServer);
        serverAndPort.add(new JLabel("Port Number:  "));
        serverAndPort.add(tfPort);
        serverAndPort.add(new JLabel(""));
        // adds the Server an port field to the GUI
        northPanel.add(serverAndPort);

        // the Label and the TextField
        label = new JLabel("Enter your username below and click Log in", SwingConstants.CENTER);
        northPanel.add(label);

        northPanel.add(textField);
        frame.getContentPane().add(northPanel,"North");
        /* The received messages area */
        frame.getContentPane().add(new JScrollPane(messageArea), "Center");

        /* Buttons */
        login = new JButton("Login");
        logout = new JButton("Logout");
        logout.setEnabled(false);   // you have to login before being able to logout

        JPanel southPanel = new JPanel();
        southPanel.add(login);
        southPanel.add(logout);
        frame.getContentPane().add(southPanel,"South");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setVisible(true);
        frame.pack();


               // Add Listeners
        textField.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e){
              if(connected){
              out.print(textField.getText()+"\n");
              out.flush();
              textField.setText(""); }
              else return;
            }
          });

        login.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e){
              finalClient fc = new finalClient(defaultHost,defaultPort);
              out.print(textField.getText() + "\n");
              out.flush();
              textField.setText("");
              login.setEnabled(false);
              logout.setEnabled(true);
              label.setText("Enter your message below");
              connected = true; 
              try{
              fc.run();  
              }
              catch(IOException io){
                System.out.println("Can't connect");
              }

            }
        });


        logout.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e){
              frame.dispose();
              System.out.println("Client closed");            
            }
        });
    }

    private void run() throws IOException {
        Socket clientSocket = new Socket(defaultHost, defaultPort);
        BufferedReader inFromUser = new BufferedReader(
            new InputStreamReader(clientSocket.getInputStream()));
        out = new PrintWriter(clientSocket.getOutputStream(), true);
        BufferedReader inFromServer = new BufferedReader(new InputStreamReader(
        clientSocket.getInputStream()));
        while (true){
              modifiedSentence = inFromServer.readLine();
          //messageArea.append(modifiedSentence + "\n");
          Matcher m = msgre.matcher(modifiedSentence);
          m.find();
          String vdeltas = m.group(1);
          String msg = m.group(2);
          messageArea.append(msg+"\n");
          Matcher vectorM = vclock.matcher(vdeltas);
          while(vectorM.find()){
            long indx = Long.parseLong(vectorM.group(1));
            long value = Long.parseLong(vectorM.group(2));
            lastClock.put(indx,value);
          }
          Message nmg = new Message(lastClock,msg);
          received.add(nmg);
          Collections.sort(received, new Comparator<Message>() {
            public int compare(Message a, Message b){
              //return 0;
              if(a.isLess(b))
                return -1;
              else if(a.isEqual(b))
                return 0;
              else
                return 1;
            }

          });
          updateMessages();
          //messageArea.append(modifiedSentence + "\n");
        }
  //clientSocket.close();
    }

  public void updateMessages() {
    StringBuilder sb = new StringBuilder();
    for(Message m : received) {
      sb.append(m);
      sb.append("\n");
    }
    messageArea.setText(sb.toString());
    messageArea.setCaretPosition(messageArea.getDocument().getLength()); // Scrolls auto to the button
  }

    public static void main(String[] args) throws Exception {
        new finalClient("localhost", 9000); 
        //program.frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        //program.frame.setVisible(true);
        //program.run();

    }

would it even make any difference? They are stored in defaultServer and defaultPort variables, so I can just read them from those? Somehow I don't want to create new GUI when clicking log in, more like just connect with the current values on the already running one

A good start would be to separate the GUI code from the newtworking code. Refactor it into two classes so you can create and swap a new instance of the network class without creating a new GUI class instance.

Was hopping to avoid that James but if no other solutions I guess i'd have to :p

Well, it's not strictly necessary, but my opinion is that in the end it will be the easiest way. It's also good practice to separate GUI from the underlying functionality, so the things you will learn doing it will be valuable.

I c, but I'd really rather keep them in 1 file for this application :s Is there any way to refer to "this" when clicking login and the parameters of defaultHost and defaultPort to be refered to it? The problem with creating new GUI is on the new one i'd have to click login again which will create another gui and so on into an infinite loop .. Also the run() method seems to return exception cought pretty much every time when I run the program but it worked fine when I had it in the main, any ideas? :p Sorry to bother but i already tried everything I could think of myself.. :P

You can have 2 classes in one file - only one can be public but you can have as many others as you want. If you want to create one GUI but have that work with multiple connections/sessions then 2 classes is the way to go. If you really want to do it one class that's up to you, but the only advice I can give is the advice I already gave ;)

Just saying you get an exception is no help at all. Every Exception comes with a complete description of what the problem was and exactly where it happened. Instead of just throwing the exception and hoping for the best, catch it and call its printStackTrace() method.

  • use JFormattedTextField with input mask or add DocumentFilter with Regex to JTextField instead of plain vanilla JTextField

  • you have an issue with Concurency in Swing, your code block a Swing GUI untill all events ended (there is possible to lost part of events for Swing GUI), use Runnable#Thread or SwingWorker for Socket, FileIO, JDBC, etc (moving hard and long running code to WorkersThreads), meaning every code inside ActionListeners should be moved to WorkersThread

  • all updates must be done on EDT (updates to JTextArea), should be wrapped into invokeLater (1st aid in this case, see my descirption in previous point)

  • use standard for moving in JScrollPane for JTextComponents (doesn't works if updates are out of EDT)

    DefaultCaret caret = (DefaultCaret) messageArea.getCaret();
    caret.setUpdatePolicy(DefaultCaret.ALWAYS_UPDATE);

  • login.setEnabled(false); and logout.setEnabled(true); shouldn't be works correctly without special woodoo, have to split to two separate events, e.g. another Swing Action (setEnabled is possible to dedicate to the childs/parents)

Edited 2 Years Ago by mKorbel

This question has already been answered. Start a new discussion instead.