I'm currently coding an instant messenger app. I started with a basic client/server setup which is functioning correctly. However, when I launch the Client () class from Login.java (after first running Server.java), the JFrame appears, but completely blank, i.e. the elements such as the conversation panel, user text input field etc. are not present. This is bizarre, because the server indicates that the Client has connected, but I cannot type/see anything in the Client form.
If I launch the Server and connect the client directly (i.e. without launching it from Login.java) both the client and server function perfectly and can converse together.
Strangely, when I launch Client.java from Login.java without the server running, the window appears as it should with elements intact (but obviously unusable since it is not connected to the server). Furthermore, when I close Server.Java, Client.Java reverts to displaying all elements, but again is unusable without the server connection.
Any help is greatly appreciated. Thanks.
Login.Java:
import java.awt.*;//contains layouts, buttons etc.
import java.awt.event.*; //contains actionListener, mouseListener etc.
import javax.swing.*; //allows GUI elements
public class Login extends JFrame implements ActionListener, KeyListener {
private JLabel usernameLabel = new JLabel("Username/Email:");
private JLabel userPasswordLabel = new JLabel("Password:");
public JTextField usernameField = new JTextField();
private JPasswordField userPasswordField = new JPasswordField();
private JLabel status = new JLabel("Status: Not yet logged in.");
private JButton loginButton = new JButton("Login");
private JButton registerButton = new JButton("New User");
public Login() {
super("Please Enter Your Login Details...");//titlebar
setVisible(true);
setSize(400, 250);
this.setLocationRelativeTo(null); //places frame in center of screen
this.setResizable(false); //disables resizing of frame
this.setLayout(null); //allows me to manually define layout of text fields etc.
ImageIcon icon = new ImageIcon("bin/mm.png");
JLabel label = new JLabel(icon);
this.add(usernameLabel);
this.add(userPasswordLabel);
this.add(usernameField);
this.add(userPasswordField);
this.add(loginButton);
this.add(registerButton);
this.add(status);
this.add(label);
label.setBounds(0, 0, 400, 70);
usernameLabel.setBounds(30, 90, 120, 30); //(10, 60, 120, 20);
userPasswordLabel.setBounds(30, 115, 80, 30);//(10, 85, 80, 20);
usernameField.setBounds(150, 90, 220, 30);
userPasswordField.setBounds(150, 115, 220, 30);
loginButton.setBounds(150, 160, 110, 25);
registerButton.setBounds(260, 160, 110, 25);
status.setBounds(30, 190, 280, 30);
status.setForeground(new Color(50, 0, 255)); //sets text colour to blue
loginButton.addActionListener(this);
registerButton.addActionListener(this);
registerButton.setEnabled(false);
userPasswordField.addKeyListener(this);
}
@Override
public void keyTyped(KeyEvent e) {
}
@Override
public void keyPressed(KeyEvent e) {
}
@Override
public void keyReleased(KeyEvent e) {
}
@Override
public void actionPerformed(ActionEvent e) {
if (e.getSource() == loginButton) {
String userName = usernameField.getText();
String password = userPasswordField.getText();
if (userName.equals("mick") && password.equals("mick")) {
status.setText("Status: Logged in.");
this.setVisible(false);
new Client("127.0.0.1").startRunning();
} else {
status.setText("Status: Password or username is incorrect.");
status.setForeground(new Color(255, 0, 0)); //changes text colour to red
}
}
}
}
Client.java:
import java.io.*;
import java.net.*;
import java.awt.*;
import java.awt.event.*;
import java.util.Date; //timestamp functionality
import javax.swing.*;
public class Client extends JFrame { //inherits from JFrame
//1. Creating instance variables
private JTextField userText; //where user inputs text
private JTextArea chatWindow; //where messages are displayed
private String fullTimeStamp = new java.text.SimpleDateFormat("dd/MM/yyyy HH:mm:ss").format(new Date());
//fullTimeStamp - MM = months; mm = minutes; HH = 24-hour cloc
private ObjectOutputStream output; //output from Client to Server
private ObjectInputStream input; //messages received from Server
private String message = "";
private String serverIP;
private Socket connection;
//2. Constructor (GUI)
public Client(String host) { //host=IP address of server
super("Mick's Instant Messenger [CLIENT]");
serverIP = host; //placed here to allow access to private String ServerIP
userText = new JTextField();
userText.setEditable(false);
userText.addActionListener(
new ActionListener() {
public void actionPerformed(ActionEvent event) {
sendMessage(event.getActionCommand()); //For this to work, must build sendData Method
userText.setText(""); //resets userText back to blank, after message has been sent to allow new message(s)
}
}
);
add(userText, BorderLayout.SOUTH);
chatWindow = new JTextArea();
add(new JScrollPane(chatWindow), BorderLayout.CENTER); //allows you to scroll up and down when text outgrows chatWindow
chatWindow.setLineWrap(true); //wraps lines when they outgrow the panel width
chatWindow.setWrapStyleWord(true); //ensures that above line wrap occurs at word end
setSize(400, 320);
this.setLocationRelativeTo(null); //places frame in center of screen
setVisible(true);
}
//3. startRunning method
public void startRunning() {
try {
connectToServer(); //unlike Server, no need to wait for connections. This connects to one specific Server.
setupStreams();
whileChatting();
} catch (EOFException eofException) {
//Display timestamp for disconnection
showMessage("\n\n" + fullTimeStamp);
showMessage("\nConnection terminated by CLIENT! ");
} catch (IOException ioException) {
ioException.printStackTrace();
} finally {
closeCrap();
}
}
//4. Connect to Server
void connectToServer() throws IOException {
showMessage(" \n Attempting connection to SERVER... \n");
connection = new Socket(InetAddress.getByName(serverIP), 6789);//Server IP can be added later
showMessage(" Connected to: " + connection.getInetAddress().getHostName()); //displays IP Address of Server
}
//5. Setup streams to send and receive messages
private void setupStreams() throws IOException {
output = new ObjectOutputStream(connection.getOutputStream());
output.flush();
input = new ObjectInputStream(connection.getInputStream());
showMessage("\n Streams are now setup! \n");
}
//6. While chatting method
private void whileChatting() throws IOException {
//Display timestamp for connection
showMessage("\n" + fullTimeStamp);
ableToType(true);
String timeStamp = new java.text.SimpleDateFormat("HH:mm:ss").format(new Date());//timestamp
do {
try {
message = (String) input.readObject(); //read input, treat as String, store in message variable
showMessage("\n" + message);
} catch (ClassNotFoundException classNotfoundException) {
showMessage("\n I don't know that object type");
}
//***broken by timestamp?***
} while (!message.equalsIgnoreCase("SERVER " + "[" + timeStamp + "]" + ": " + "END")); //Conversation happens until Server inputs 'End'
}
//7. Close the streams and sockets
private void closeCrap() {
showMessage("\n\nClosing streams and sockets...");
ableToType(false);//disable typing feature when closing streams and sockets
try {
output.close();
input.close();
connection.close();
} catch (IOException ioException) {
ioException.printStackTrace(); //show error messages or exceptions
}
}
//8. Send Messages to Server
private void sendMessage(String message) {
try {
String timeStamp = new java.text.SimpleDateFormat("HH:mm:ss").format(new Date());//timestamp
output.writeObject("CLIENT" + " [" + timeStamp + "]" + ": " + message);
output.flush();
showMessage("\nCLIENT" + " [" + timeStamp + "]" + ": " + message);
} catch (IOException ioexception) {
chatWindow.append("\n Error: Message not sent!");
}
}
//9.change/update chatWindow
private void showMessage(final String m) {
SwingUtilities.invokeLater(
new Runnable() {
public void run() {
chatWindow.setEditable(false); //disallows text editing in chatWindow
chatWindow.append(m); //appends text, which was passed in from above
}
}
);
}
//10. Lets user type
private void ableToType(final boolean tof) {
SwingUtilities.invokeLater(
new Runnable() {
public void run() {
userText.setEditable(tof); //passes in 'true'
}
}
);
}
}