Chat System - Chat GUI Commands [Members] and Receiving Messages

Introduction: This tutorial is the fourteenth in my Java Network Programming using KryoNet series, or ninth in creating a chat client and server system, in which we are going to be making the rest of the ChatGUI work from the previous tutorial. Previous: In the previous tutorial we created a chat GUI to allow the user to physically send and receive messages visually. Sending worked but we had not yet added the functionality of receiving new messages. 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: This tutorial we are carrying on from the previous tutorial by adding receiving messages functionality to the chat GUI and a list of connected members. Receiving Messages: We currently receive messages in the client by listening for the Packet2Message packet of an incoming data packet. Instead of just outputting the message within the Packet2Message packet to the console, we are now going to append the message to the bottom of area1 in the chat GUI (the chat room text box itself). So first we create method in ChatGUI to add the message...
  1. public void addMessage(String message) {
  2. area1.append(message + "\n");
  3. }
The above method simple adds the parameter message string to the bottom of the area1 JTextArea box and adds a new line ready for the next message. So now we want to run the method somehow. We want to use the same instance of ChatGUI that is currently running, but we don't have a way to access it since we simply call a new ChatGUI from the login button once it is successful at logging in to the server through the LoginGUI class. So in the main ClientCustom class we are going to create a new ChatGUI object...
  1. static ChatGUI chatGUI;
-It is important not to initiate the object here. Also ensure the new ChatGUI object is in the variable scope along with the other two static boolean variable we have, otherwise we are unable to access it from LoginGUI next.- Now we want to initiate the chatGUI object once we log in successfully. So in the loginGUI button listener where we create a new ChatGUI instance we are going to initiate the chatGUI object instead... -Replace-:
  1. new ChatGUI(client);
-With-:
  1. ClientCustom.chatGUI = new ChatGUI(client);
Now we can use the chatGUI object to add a new message. So in the main listener where we receive a Packet2Message packet, we are going to use that method through the chatGUI object we have now created and initiated...
  1. if(object instanceof Packet2Message) {
  2. System.out.println("Packet2Message Received.");
  3. Packet2Message packet = (Packet2Message) object;
  4. //System.out.println("Received message: " + packet.message);
  5. try {
  6. chatGUI.addMessage(packet.message);
  7. }catch (Exception ex) {
  8. System.out.println("Message received while chatGUI was not initiated...");
  9. }
  10. }
We add a try and catch statement because we could receive a message while the client is still trying to login meaning the chatGUI object would be null and it would throw an error when trying to use the addMessage method through it. Member List: Finally we are going to add a way for the user to enter commands to the chat box. The commands will all start with a forward slash (/) so where we handle sending the message, we are going to ensure that we are not sending a command...
  1. button1.addActionListener(new ActionListener() {
  2. public void actionPerformed(ActionEvent event) {
  3. String entered = area2.getText();
  4. System.out.println(entered);
  5. System.out.println(entered.startsWith("/"));
  6. if (entered.startsWith("/")) {
  7. System.out.println("Command");
  8. //Command, don't send a message packet
  9. if (entered.equalsIgnoreCase("/members") || entered.equals("/list")) {
  10. Packet5Members packet = new Packet5Members();
  11. client.sendTCP(packet);
  12. addMessage("[" + entered + "] Getting members list...");
  13. }
  14. }else{
  15. //Message, send a message packet instead of processing a command.
  16. Packet2Message packet = new Packet2Message();
  17. packet.message = area2.getText();
  18. client.sendTCP(packet);
  19. area2.setText("");
  20. }
  21. }
  22. });
For those of you who are eagle eyed, you may notice that we are now using a Packet5Members which we have not yet created. This packet will ask the server to return a list of connected members. Lets make this now...
  1. package Packets;
  2.  
  3. public class Packet5Members extends Packet{
  4. public String[] names;
  5. }
-Ensure this packet is in your packets package of both your client and server java projects. Also ensure you have imported the new packet.- As you can see, this new packet contains a single dimensioned array of strings named "names". Each of the usernames of the clients connected to the server will be added to this and sent back to the client requesting the names. Let's do this now, in the server listener...
  1. else if(object instanceof Packet5Members) {
  2. Packet5Members packet = (Packet5Members) object;
  3. packet.names = clientHandler.getMembers();
  4. connection.sendTCP(packet);
  5. }
So once we receive a Packet5Members packet on our server listener data received method, we area creating another new one, settings its names string array of data to the information returned by a new method named getMembers in our clientHandler and returning the packet along the same connection (to the same client) that sent th requesting packet data. Now we need to create the getMembers method in our clientHandler...
  1. public String[] getMembers() {
  2. ArrayList<String> members = new ArrayList<String>();
  3. for (CustomClient c : this.clients){
  4. members.add(c.getUsername());
  5. }
  6. return members.toArray(new String[members.size()]);
  7. }
Finally we need to process the returning array to the client. In the client listener...
  1. else if(object instanceof Packet5Members) {
  2. Packet5Members packet = (Packet5Members) object;
  3. for (String entry : packet.names) {
  4. chatGUI.addMessage("[Connected Client] " + entry);
  5. }
  6. chatGUI.addMessage("=== End Connected Clients List ===");
  7. }
The very last thing we need to do is register all the classes now being used in the transmissions...
  1. client.getKryo().register(Packet5Members.class);
  2. client.getKryo().register(String[].class);
And...
  1. server.getKryo().register(Packet5Members.class);
  2. server.getKryo().register(String[].class);

Add new comment