Chat System - Login GUI & Altering Messages

Introduction: This tutorial is the twelfth in my Java Network Programming using KryoNet series, or seventh in creating a chat client and server system, in which we are going to be altering received messages and creating the login GUI for the client. Previous: In the previous tutorial we created a way to stop two clients from having the same username, therefore making all client usernames unique. The System: We are going to give the user a GUI to interact with the system - to send messages and see the currently connected members of the chat. When a client connects, add them to a list. Send incoming messages to everyone within the client list except the sender - or send them one back saying that it is received, as confirmation. This Tutorial: Since we set up the unique usernames in the previous tutorial, we are now going to create a working login GUI for the client instead of just using a console based Command Line Interface (CLI). We are also going to be slightly altering messages. Message Altering: Now that we are properly building a way to handle multiple clients within one chat room on a server, we need to know who has sent what messages. So we can simply alter the circulate messages method in our client handler on our server. We simply add the username of the sender to the beginning of the message followed by a colon, a space then the message (user: message)...
  1. public void circulateMessage(Connection connection, Packet2Message packet) {
  2. String msg = packet.message;
  3. packet.message = getUsername(connection) + ": " + msg;
  4. for (CustomClient c : this.clients) {
  5. if (c.getConnection().getID() != connection.getID()){
  6. System.out.println("Sending to " + c.getUsername());
  7. c.getConnection().sendTCP(packet);
  8. }
  9. }
  10. }
It sets a new string variable named msg to the message within the packet, then it sets the message within the packet to the username of the connection returned by our getUsername method which accepts one parameter of a connection, then we put a colon, space and the message held in our msg string variable. Login GUI: Create a new class named LoginGUI within our Clients default package - or where your other classes are saved) - and make it extend JFrame...
  1. import java.awt.Dimension;
  2. import java.awt.event.ActionEvent;
  3. import java.awt.event.ActionListener;
  4.  
  5. import javax.swing.JButton;
  6. import javax.swing.JFrame;
  7. import javax.swing.JLabel;
  8. import javax.swing.JTextField;
  9.  
  10. import com.esotericsoftware.kryonet.Client;
  11.  
  12. public class LoginGUI extends JFrame{
  13.  
  14. JLabel label1 = new JLabel("Enter the username to login to the server:");
  15. JTextField text1 = new JTextField();
  16. JButton button1 = new JButton("Log in");
  17. Client client;
  18.  
  19. public LoginGUI(final Client cclient) {
  20. client = cclient;
  21. Dimension dim = new Dimension(400, 250);
  22. setSize(dim);
  23. setPreferredSize(dim);
  24. setMaximumSize(dim);
  25. setMinimumSize(dim);
  26. setResizable(false);
  27. setTitle("Client Login GUI");
  28. setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
  29. setLocationRelativeTo(null);
  30. setLayout(null);
  31. setVisible(true);
  32.  
  33. label1.setSize(300, 40);
  34. label1.setLocation(10, 10);
  35. label1.setLayout(null);
  36.  
  37. text1.setSize(300, 40);
  38. text1.setLocation(10, 50);
  39. text1.setLayout(null);
  40.  
  41. button1.setSize(100, 40);
  42. button1.setLocation(10, 120);
  43. button1.setLayout(null);
  44.  
  45. add(label1);
  46. add(text1);
  47. add(button1);
  48. }
  49. }
So that is the main visuals, now we want to add a button listener on to the login button to make it use the connect method in our ClientCustom class. Add this just under our "add" section...
  1. button1.addActionListener(new ActionListener() {
  2. public void actionPerformed(ActionEvent event) {
  3. ClientCustom.connect(client, text1.getText());
  4. }
  5. });
As you can see, that listener will then run the connect method in our ClientCustom class and pass it the client (global variable, set on the constructor) and the text entered in to the textbox, the log in name. Now we want to alter the connect method in our main ClientCustom class to accept a username string as well since we now accept it from the JFrame and not the scanner within the method... -Previous-:
  1. public void connect(Client client) {
  2. System.out.println("Enter your username for the new chat room... ");
  3. Scanner userScan = new Scanner(System.in);
  4. while (true) {
  5. String loggedInUsername = userScan.nextLine();
  6. Packet3UsernameReq req = new Packet3UsernameReq();
  7. req.username = loggedInUsername;
  8. client.sendTCP(req);
  9. while (!userServerRes) {
  10. try {
  11. System.out.println("Sleeping...");
  12. Thread.sleep(500);
  13. }catch (Exception ex) {}
  14. }
  15. if (userServerAvailable) {
  16. System.out.println("That username is already taken. Please enter a new one... ");
  17. userServerRes = false; //Reset global booleans used for server username response
  18. }else{ //false=available
  19. System.out.println("Connecting...");
  20. Packet1Connect con = new Packet1Connect();
  21. con.name = loggedInUsername;
  22. client.sendTCP(con);
  23. System.out.println("Connected as " + loggedInUsername);
  24. userServerRes = false; //Reset global booleans used for server username response
  25. break;
  26. }
  27. }
  28. }
-New-:
  1. public static void connect(Client client, String loggedInUsername) {
  2. Packet3UsernameReq req = new Packet3UsernameReq();
  3. req.username = loggedInUsername;
  4. client.sendTCP(req);
  5. while (!userServerRes) {
  6. try {
  7. System.out.println("Sleeping...");
  8. Thread.sleep(500);
  9. }catch (Exception ex) {}
  10. }
  11. if (userServerAvailable) {
  12. System.out.println("That username is already taken. Please enter a new one... ");
  13. userServerRes = false; //Reset global booleans used for server username response
  14. }else{ //false=available
  15. System.out.println("Connecting...");
  16. Packet1Connect con = new Packet1Connect();
  17. con.name = loggedInUsername;
  18. client.sendTCP(con);
  19. System.out.println("Connected as " + loggedInUsername);
  20. userServerRes = false; //Reset global booleans used for server username response
  21. }
  22. }
Since we have to make the method static, we also need to make the booleans static...
  1. static boolean userServerRes = false;
  2. static boolean userServerAvailable = false;
Finally instead of running the connect method like so...
  1. connect(client);
(remove the above line and add the below line). We want to run a new instance of the new LoginGUI class and give it the client...
  1. new LoginGUI(client);
Finished! That's the login GUI finished, the only other GUI related things we have to do are; Create a main Chat GUI. Move the output to the console to somewhere within the GUI. Add more features to the GUIs.

Add new comment