how can i display components in GUI server without a connected client? - java

I have a tabbed Jframe named Version3 which implements Runnable. Into it i have 3 JPanels in different tabbs.Next to those tabs i have a textarea.
I want my GUI to listen for messages and display them in the textarea. I tried to make my GUI Version3 a server which listens all the time in case it receives any message from client.
java.awt.EventQueue.invokeLater(new Runnable(){
public void run(){
Version3 v=new Version3();
v.setVisible(true);
v.listenTo();
}
});
I made my GUI Version3 a server but when i run the program the components of the GUI doesn't show until it's connected to client.I just have a blank GUI window with no components. Any ideas how to display all my components on my GUI without a client connected?

I made my GUI Version3 a server but when i run the program the
components of the GUI doesn't show until it's connected to client.I
just have a blank GUI window with no components. Any ideas how to
display all my components on my GUI without a client connected?
I think it's more than likely that you're blocking the Event Dispatching Thread (a.k.a. EDT) while your class is trying to connect to the client. That's the reason why it works when you have connection but it doesn't when you haven't. The EDT is a single and special thread where Swing component creation and updates take place. If you have a heavy task running in the EDT then your GUI will freeze and Swing components won't be able to work (or even display).
Take a look to Concurrency in Swing trail to learn about concurrency in Swing.
Off-topic: please consider add your code in future questions. As #alex2410 suggested it's better if you include a SSCCE demonstrating your problem.

Server:
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.IOException;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class Server extends JPanel {
Socket socket;
final static int PORT = 2325;
PrintWriter pr;
public ServerSocket serverSocket;
JButton btn_sendHello;
int counter;
Thread thread;
public Server() {
counter = 0;
btn_sendHello = new JButton("Send hello");
btn_sendHello.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
if (pr != null) {
pr.println("Hello from server " + ++counter);
}
}
});
this.add(btn_sendHello);
try {
serverSocket = new ServerSocket(PORT);
thread = new Thread(waitingClient);
thread.start();
} catch (IOException ex) {
Logger.getLogger(Server.class.getName()).log(Level.SEVERE, null, ex);
}
}
Runnable waitingClient = new Runnable() {
#Override
public void run() {
try {
socket = serverSocket.accept();
openStreams();
} catch (IOException ex) {
Logger.getLogger(Server.class.getName()).log(Level.SEVERE, null, ex);
}
}
};
private void openStreams() {
if (socket != null) {
try {
pr = new PrintWriter(socket.getOutputStream(), true);
} catch (IOException ex) {
Logger.getLogger(Server.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
JFrame frame = new JFrame();
frame.setTitle("Server");
frame.add(new Server());
frame.pack();
frame.setSize(250, 100);
frame.setLocationRelativeTo(null);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
});
}
}
Client:
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.Socket;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
public class Client extends JPanel {
final static int PORT = 2325;
private Socket socket;
private BufferedReader fromServer;
private JTextField jtfield;
Thread threadReceive;
public Client() {
jtfield = new JTextField(12);
this.add(jtfield);
try {
socket = new Socket("localhost", PORT);
openStreams();
Thread thread = new Thread(receives);
thread.start();
} catch (IOException ex) {
Logger.getLogger(Client.class.getName()).log(Level.SEVERE, null, ex);
}
}
Runnable receives = new Runnable() {
#Override
public void run() {
while (true) {
synchronized (this) {
if (socket != null) {
processServerInput();
}
}
}
}
};
private void openStreams() {
try {
if (socket != null) {
fromServer = new BufferedReader(new InputStreamReader(socket.getInputStream()));
}
} catch (IOException ex) {
Logger.getLogger(Client.class.getName()).log(Level.SEVERE, null, ex);
}
}
private void processServerInput() {
try {
String line = fromServer.readLine();
while (!(line.equals("Bye"))) {
jtfield.setText(line);
line = fromServer.readLine();
}
} catch (IOException ex) {
Logger.getLogger(Client.class.getName()).log(Level.SEVERE, null, ex);
}
}
void closeStreams() {
try {
fromServer.close();
socket.close();
} catch (IOException ex) {
Logger.getLogger(Client.class.getName()).log(Level.SEVERE, null, ex);
}
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
JFrame frame = new JFrame();
frame.setTitle("Client");
frame.add(new Client());
frame.pack();
frame.setSize(250, 100);
frame.setLocationRelativeTo(null);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
});
}
}

Related

SocketChannel sockets not reading data

Here is my code. From the TestServer, I'm trying to send data through an outputstream and have it received from the test client. I'm using a SocketChannel because I need the client to listen on 3 ports at the same time. At the moment, i'm only trying to read from one socket. However it doesnt seem to be receiving any data from the server. For the run method of KBThread, if I uncomment the nodata println, that will execute over and over.
TestServer.java
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.*;
public class TestServer extends JPanel implements KeyListener, MouseListener, MouseMotionListener {
private final int MAX_CLIENTS = 8;
JPanel listenerPanel = new JPanel();
JFrame listenerFrame = new JFrame();
static DataOutputStream kbOut;
static DataOutputStream mOut;
static Socket dataSocket;
public TestServer() {
this.setFocusable(true);
listenerPanel.addKeyListener(this);
listenerPanel.addMouseMotionListener(this);
listenerFrame.add(listenerPanel);
listenerFrame.setSize(1376,808); // 10 more x, 40 more y.
listenerFrame.setVisible(true);
listenerFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
listenerPanel.requestFocusInWindow();
}
public static void main(String[] args) {
new TestServer().startServer();
}
public void startServer() {
final ExecutorService clientProcessingPool = Executors.newFixedThreadPool(MAX_CLIENTS);
Runnable serverTask = () -> {
try {
ServerSocket serverSocket = new ServerSocket(1111);
System.out.println("Waiting for clients.");
while (true) {
Socket clientSocket = serverSocket.accept();
clientProcessingPool.submit(new ClientTask(clientSocket));
}
} catch (IOException ex) {
System.err.println("Error with client socket.");
}
};
Thread serverThread = new Thread(serverTask);
serverThread.start();
}
private class ClientTask implements Runnable {
private final Socket clientSocket;
private ClientTask(Socket clientSocket) {
this.clientSocket = clientSocket;
}
#Override
public void run() {
try {
String clientIP = clientSocket.getInetAddress().getHostAddress();
System.out.println("Client connected from " + clientIP);
Socket kbSocket = new Socket(clientIP, 1112);
System.out.println("Keyboard socket connected to " + clientIP);
kbOut = new DataOutputStream(kbSocket.getOutputStream());
Socket mSocket = new Socket(clientIP, 1113);
System.out.println("Mouse socket connected to " + clientIP);
mOut = new DataOutputStream(mSocket.getOutputStream());
//new TestServer().startKBServer(clientIP);
//new TestServer().startMServer(clientIP);
try {
clientSocket.close();
} catch (IOException ex) {
}
} catch (IOException ex) {
Logger.getLogger(TestServer.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
public void startKBServer(String clientAddress) {
Runnable kbTask = () -> {
try {
Socket kbSocket = new Socket(clientAddress, 1112);
System.out.println("Keyboard socket connected to " + clientAddress);
new KBTask(kbSocket);
} catch (IOException ex) {
System.out.println("Error Calling Back " + clientAddress);
}
};
Thread kbThread = new Thread(kbTask);
kbThread.start();
}
private class KBTask implements Runnable {
private final Socket kbSocket;
private KBTask(Socket kbSocket) {
this.kbSocket = kbSocket;
}
#Override
public void run() {
try {
kbOut = new DataOutputStream(kbSocket.getOutputStream());
} catch (IOException ex) {
Logger.getLogger(TestServer.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
#Override
public void keyPressed(KeyEvent ke) {
try {
int key = ke.getKeyCode();
System.out.println("Key Pressed: " + key);
kbOut.writeInt(key);
kbOut.flush();
} catch (IOException ex) {
System.out.println("Error writing key data to server");
}
}
#Override
public void keyReleased(KeyEvent ke) {
try {
int key = ke.getKeyCode();
System.out.println("Key Pressed: " + -key);
kbOut.writeInt(-key);
kbOut.flush();
} catch (IOException ex) {
System.out.println("Error writing -key data to server");
}
}
#Override
public void mouseMoved(MouseEvent me) {
try {
int mouseX = me.getX();
int mouseY = me.getY();
if (mOut != null) {
mOut.writeInt(mouseX);
mOut.writeInt(mouseY);
mOut.flush();
System.out.println("Mouse Moved To: " + mouseX + "," + mouseY);
}
} catch (IOException | NullPointerException ex) {
System.out.println("Error writing mouse data to server");
}
}
#Override
public void mouseClicked(MouseEvent me) {
}
#Override
public void mousePressed(MouseEvent me) {
}
#Override
public void mouseReleased(MouseEvent me) {
}
#Override
public void mouseEntered(MouseEvent me) {
}
#Override
public void mouseExited(MouseEvent me) {
}
#Override
public void mouseDragged(MouseEvent me) {
}
#Override
public void keyTyped(KeyEvent ke) {
}
}
TestClient.java
import java.awt.AWTException;
import java.awt.Robot;
import java.io.BufferedReader;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.ConnectException;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.Iterator;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class TestClient {
private final static String SERVER_IP = "192.168.0.50";
JPanel clientPanel = new JPanel();
JFrame clientFrame = new JFrame();
public void setupGUI() {
clientFrame.add(clientPanel);
clientFrame.setSize(200,200);
clientFrame.setVisible(true);
clientFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
clientPanel.requestFocusInWindow();
}
public static void main(String[] args) {
try {
new TestClient().setupGUI();
Robot keyRobot = new Robot();
Socket firstSocket = new Socket(SERVER_IP, 1111);
System.out.println("Connected to Commander. Address sent. Waiting for callback.");
firstSocket.close();
Selector selector = Selector.open();
int ports[] = new int[] { 1112, 1113 };
for (int port : ports) {
ServerSocketChannel serverChannel = ServerSocketChannel.open();
serverChannel.configureBlocking(false);
serverChannel.socket().bind(new InetSocketAddress(port));
serverChannel.register(selector, SelectionKey.OP_ACCEPT);
}
while (true) {
// After the 2 accept methods fire, it stops here and program doesnt continue.
selector.select();
Set setKeys = selector.selectedKeys();
Iterator selectedKeys = setKeys.iterator();
while (selectedKeys.hasNext()) {
SelectionKey selectedKey = (SelectionKey) selectedKeys.next();
if (selectedKey.isAcceptable()) {
SocketChannel socketChannel = ((ServerSocketChannel) selectedKey.channel()).accept();
socketChannel.configureBlocking(false);
switch (socketChannel.socket().getLocalPort()) {
case 1112:
System.out.println("Keyboard socket open.");
Runnable kbr = new KBThread(socketChannel.socket());
new Thread(kbr).start();
break;
case 1113:
System.out.println("Mouse socket open.");
break;
}
}
selectedKeys.remove();
}
}
} catch (ConnectException ece) {
System.out.println("Failed to connect to server: " + SERVER_IP);
} catch (IOException | AWTException eio) {
Logger.getLogger(TestClient.class.getName()).log(Level.SEVERE, null, eio);
}
}
private static class KBThread implements Runnable {
private final Socket kbSocket;
private int dataID = 0;
private KBThread(Socket kbSocket) {
this.kbSocket = kbSocket;
}
#Override
public void run() {
try {
DataInputStream kbDis = new DataInputStream(kbSocket.getInputStream());
while (true) {
try {
if (kbDis.available() > 0) {
dataID = kbDis.readInt();
System.out.println(dataID);
}
//else System.out.println("noData");
} catch (IOException ex) {
Logger.getLogger(TestClient.class.getName()).log(Level.SEVERE, null, ex);
}
}
} catch (IOException ex) {
Logger.getLogger(TestClient.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
}
This is not how IO multiplexing is supposed to work.
First, don't remove from selectedKeys - after you accepted two connections there's nothing to select on, so the loop in the main thread blocks, and event if new connections are arriving you are not accepting them anymore. - this was wrong, I was confused about Java iterators, it's been a long time ...
Then, once a connection is accepted and marked non-blocking, add it to the same selector with OP_READ. Check for readable event in the loop, read from the socket. You don't need threads for this.
Alternatively, if you want to go with threads, don't set accepted client connection as non-blocking, just do regular reads from it in the dedicated thread.
Edit 0:
The best advise I can offer is to go over some good Java NIO tutorial. There many on the Intenet, but you can start here:
http://docs.oracle.com/javase/1.5.0/docs/guide/nio/example/index.html
http://tutorials.jenkov.com/java-nio/index.html
Don't have enough rep for comments so posting as answer. I am no expert but I believe you will have to use a PrintWriter on sockets output stream to pass the text back and forth. Here thisClient is a socket.
writer = new PrintWriter(thisClient.getOutputStream());
System.out.println("Transmitting");
writer.println(msg);
writer.flush();

issue in sending the socket output to GUI

I wrote this simple multi threaded chatroom, and I am trying to send the client/server output to GUI to display it in chatroom text area but I get null pointer exception at the following line:
output.write(line + "\n");
here is the full code for GUI:
import java.awt.*;
import javax.swing.*;
import javax.swing.JTextField;
import javax.swing.JFrame;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.io.IOException;
import javax.swing.JButton;
import java.io.Writer;
public class GUI {
private JFrame frame;
private JButton btnSend, btnConnect;
private JTextArea txtChat;
private JTextField fldText, fldName;
private JList clientList;
private DefaultListModel listModel;
private JScrollPane sc, scClients;
private JPanel jpS2All, jpS2Client, jpS2Text;
private String Name;
private JLabel lblErr;
private Writer output;
public GUI(String Name, Writer output) {
this.Name = Name;
this.output = output;
}
public GUI() {
}
class handler implements ActionListener, MouseListener {
handler(String Name) {
}
handler() {
}
#Override
public void actionPerformed(ActionEvent e) {
clients(); //it seems this line made the error because it creates the
listModel.addElement(Name);//gui and sends the output to textSend actionlistener
//to display it in gui
//while the output is empty, right?
//is there any way to handle this?
}
#Override
public void mouseClicked(MouseEvent e) {
fldName.setText("");
}
#Override
public void mousePressed(MouseEvent e) {
}
#Override
public void mouseReleased(MouseEvent e) {
}
#Override
public void mouseEntered(MouseEvent e) {
}
#Override
public void mouseExited(MouseEvent e) {
}
} //end of handler
class textSend implements ActionListener {
textSend(String Name, Writer output) {
}
#Override
public void actionPerformed(ActionEvent e) {
String line = fldText.getText();
try {
output.write(line + "\n"); // the null exception error shows the
output.flush(); // error source at this line!
} catch (IOException ioe) {
txtChat.append("Other party hung up!");
}
String contenet = Name + ":" + output;
txtChat.append(contenet);
fldText.setText("");
}
}//end of textSend
public void creatServer() {
frame = new JFrame("enter");
frame.setBounds(50, 50, 300, 200);
btnConnect = new JButton("connect");
lblErr = new JLabel();
lblErr.setText("");
frame.add(btnConnect, BorderLayout.EAST);
fldName = new JTextField();
fldName.setText("enter your name");
fldName.addMouseListener(new handler());
btnConnect.addActionListener(new handler(getName()));
frame.add(fldName, BorderLayout.CENTER);
frame.setVisible(true);
}
public void clients() { //to create the chatroom GUI
frame = new JFrame("friends");
frame.setBounds(100, 100, 400, 400);
jpS2All = new JPanel();
txtChat = new JTextArea();
txtChat.setRows(25);
txtChat.setColumns(25);
txtChat.setEditable(false);
sc = new JScrollPane(txtChat);
jpS2All.add(sc);
frame.add(jpS2All, BorderLayout.WEST);
jpS2Text = new JPanel();
////////////////////////
fldText = new JTextField();
fldText.setColumns(34);
fldText.setHorizontalAlignment(JTextField.RIGHT);
fldText.addActionListener(new textSend(getName(), output));
jpS2Text.add(fldText);
frame.add(jpS2Text, BorderLayout.SOUTH);
/////////
jpS2Client = new JPanel();
listModel = new DefaultListModel();
clientList = new JList(listModel);
clientList.setFixedCellHeight(14);
clientList.setFixedCellWidth(100);
scClients = new JScrollPane(clientList);
frame.add(jpS2Client.add(scClients), BorderLayout.EAST);
/////////
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
frame.pack();
}//end of clients
public String getName() {
Name = fldName.getText();
return Name;
}
public void appendText(final String message) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
txtChat.append(message);
}
});
}
}
server code:
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.logging.Level;
import java.util.logging.Logger;
public class server {
public void start() throws IOException {
ServerSocket serverSocket = new ServerSocket(1234);
while (true) {
Socket socket = serverSocket.accept();
ClientThread t = new ClientThread(socket);
t.start();
}
}
public static void main(String[] args) throws IOException {
server server = new server();
server.start();
}
class ClientThread extends Thread {
Socket socket;
InputStream sInput;
OutputStream sOutput;
GUI gui = new GUI();
String Name;
ClientThread(Socket socket) {
this.socket = socket;
}
#Override
public void run() {
try {
BufferedReader sInput
= new BufferedReader(new InputStreamReader(socket.getInputStream()));
Writer sOutput = new OutputStreamWriter(socket.getOutputStream());
Name = gui.getName();
gui = new GUI(Name, sOutput);
try {
String line;
while ((line = sInput.readLine()) != null) {
gui.appendText(line);
}
} catch (IOException ex) {
Logger.getLogger(client.class.getName()).log(Level.SEVERE, null, ex);
}
} catch (IOException e) {
}
}
}
}
client side:
import java.net.*;
import java.io.*;
import java.util.logging.Level;
import java.util.logging.Logger;
public class client {
private Socket s;
private String Name;
private GUI gui;
private Writer output;
private BufferedReader input;
public void start() {
try {
s = new Socket("127.0.0.1", 1234);
} catch (IOException ex) {
}
try {
input = new BufferedReader(new InputStreamReader(s.getInputStream()));
output = new OutputStreamWriter(s.getOutputStream());
} catch (IOException eIO) {
}
Name = gui.getName();
new GUI(Name, output);
new ListenFromServer().start();
}
public static void main(String[] args) {
client cl = new client();
GUI gui = new GUI();
gui.creatServer();
}
class ListenFromServer extends Thread {
public void run() {
try {
String line;
while ((line = input.readLine()) != null) {
gui.appendText(line);
}
} catch (IOException ex) {
Logger.getLogger(client.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
}
I know my question is a bit cumbersome but I really appreciate to help me handle this issue!
I am looking at your code and it is obvious that output is null when you attempt output.write(line + "\n"); Therefore I went and looked for the possible path of execution that could leave output un-initialized. This is where debugging comes in very handy.
Here is your execution path:
In your main method of client you create a new GUI and then call gui.creatServer();
public static void main(String[] args) {
client cl = new client();
GUI gui = new GUI();
gui.creatServer();
}
output has not been assigned and is still null
in the creatServer(); method you have this line:
fldName.addMouseListener(new handler());
which the actionPerformed method of handler calls the clients(); method which has the line:
fldText.addActionListener(new textSend(getName(), output));
note output is still null
(now your textSend class doesn't even do anything inside the constructor but that aside even if it did you are still using the output variable from the GUI class)
you have the actionPerformed method in the textSend class that has the line:
output.write(line + "\n");
Without ever initializing output it is still null, which gives you the NullPointer
Please see What is a NullPointerException, and how do I fix it? as #markspace linked in the comments. In addition you should really learn how to debug small programs.
See the following links:
http://ericlippert.com/2014/03/05/how-to-debug-small-programs/
http://blogs.msdn.com/b/smallbasic/archive/2012/10/09/how-to-debug-small-basic-programs.aspx
Again in addition, consider using Anonymous classes to ease up on those lines of code, which also makes the code easier to debug and more readable.
One last thought, remember to use standard Naming Conventions for the language you are using. your code currently has a lot of incorrect lowercase classes and some uppercase methods/properties.
the error message shows that one of the variable used in the expression was null. This may be either output or line.
As chancea already mentioned, you are calling the GUI() constructor with no arguments, so the output field is not initialized. You should remove the constructor with no arguments when you have no way to initialize the output field in it and only leave the one with arguments.

Java Event-Dispatch Thread example program hangs

I have read this article on the EDT (Event Dispatch Thread) javaworld.com which shows how to correctly setup a Swing GUI on the EDT and put long running tasks which modify the GUI inside Runnables.
It all makes sense however the example program (I pasted below) where the only modification I made is a Thread.sleep(6000) to simulate a long lag makes the interface irresponsive for some seconds.
Am I missing something?
import java.awt.BorderLayout;
import java.awt.EventQueue;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.InvocationTargetException;
import java.net.URL;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;
public class ViewPage
{
public static void main(String[] args)
{
Runnable r;
r = new Runnable()
{
#Override
public void run()
{
final JFrame frame = new JFrame("View Page");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JPanel panel = new JPanel();
panel.add(new JLabel("Enter URL"));
final JTextField txtURL = new JTextField(40);
panel.add(txtURL);
frame.getContentPane().add(panel, BorderLayout.NORTH);
final JTextArea txtHTML = new JTextArea(10, 40);
frame.getContentPane().add(new JScrollPane(txtHTML),
BorderLayout.CENTER);
ActionListener al;
al = new ActionListener()
{
public void actionPerformed(ActionEvent ae)
{
txtURL.setEnabled(false);
Runnable worker = new Runnable()
{
public void run()
{
InputStream is = null;
try
{
URL url = new URL(txtURL.getText());
is = url.openStream();
final StringBuilder sb;
sb = new StringBuilder();
int b;
while ((b = is.read()) != -1)
{
sb.append((char) b);
}
Runnable r = new Runnable()
{
public void run()
{
try
{
Thread.sleep(6000);
}
catch (InterruptedException ex)
{
Logger.getLogger(ViewPage.class.getName()).log(Level.SEVERE, null, ex);
}
txtHTML.setText(sb.toString());
txtURL.setEnabled(true);
}
};
try
{
EventQueue.invokeAndWait(r);
}
catch (InterruptedException ie)
{
}
catch (InvocationTargetException ite)
{
}
}
catch (final IOException ioe)
{
Runnable r = new Runnable()
{
public void run()
{
txtHTML.setText(ioe.getMessage());
txtURL.setEnabled(true);
}
};
try
{
EventQueue.invokeAndWait(r);
}
catch (InterruptedException ie)
{
}
catch (InvocationTargetException ite)
{
}
}
finally
{
Runnable r = new Runnable()
{
public void run()
{
txtHTML.setCaretPosition(0);
txtURL.setEnabled(true);
}
};
try
{
EventQueue.invokeAndWait(r);
}
catch (InterruptedException ie)
{
}
catch (InvocationTargetException ite)
{
}
if (is != null)
{
try
{
is.close();
}
catch (IOException ioe)
{
}
}
}
}
};
new Thread(worker).start();
}
};
txtURL.addActionListener(al);
frame.pack();
frame.setVisible(true);
}
};
EventQueue.invokeLater(r);
}
}
Am I missing something?
Yes.
Runnable is just an interface not another thread.
Here with this line you are wrapping the call to execute later in the Event Dispatch Thread.
EventQueue.invokeLater(r); // you can use SwingUtilities.invokeLater(r) too
Then you call
Thread.sleep(6000);
This is executed in EDT and make irresponsive the gui until finish.
For long task you should use another threads or SwingWorker and for short task with some repetitions SwingTimer.
Read about Concurrency in Swing

Chat program freezes JFrame

I'm writing a simply chat client and am moving it over to a nice GUI. The constructor for the server side (client side is android) contains a list that's in the JFrame, and the first part of the server runs, but then the entire frame locks up. Does anyone see the issue? Sorry for the relatively disorganized, not cleanly commented code...
Server:
import java.awt.List;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketException;
import java.net.UnknownHostException;
public class ChatServer {
private final int CHAT_PORT = 4453;
ServerSocket sSocket;
Socket cSocket;
PrintWriter pWriter;
BufferedReader bReader;
InetAddress localAddr;
List messageList;
public ChatServer(List entList)
{
messageList = entList;
}
public synchronized void run()
{
messageList.add("Chat Server Starting...");
try {
localAddr = InetAddress.getLocalHost();
} catch (UnknownHostException e1) {
messageList.add("InnetAddress error");
}
while(true)
{
try {
sSocket = new ServerSocket(CHAT_PORT);
sSocket.setReuseAddress(true);
messageList.add("Server has IP:" + localAddr.getHostAddress());
messageList.add("Server has hostname:" + localAddr.getHostName());
messageList.add("Server has port:" + CHAT_PORT);
} catch (IOException e) {
//ERRORS
if(cSocket.isConnected())
{
messageList.add("User disconnected\n");
try {
cSocket.close();
} catch (IOException e1) {
messageList.add("Error closing client socket");
}
}
else
{
messageList.add("ERROR CREATING SOCKET\n");
}
}
try {
cSocket = sSocket.accept();
cSocket.setReuseAddress(true);
messageList.add("INFO: socket connected");
} catch (IOException e) {
messageList.add("Client Socket Error");
System.exit(-1);
}
try {
pWriter = new PrintWriter(cSocket.getOutputStream(), true);
messageList.add("INFO: Print writer opened");
} catch (IOException e) {
messageList.add("PrintWriter error");
}
try {
bReader = new BufferedReader(new InputStreamReader(cSocket.getInputStream()));
messageList.add("INFO: buffered reader opened");
} catch (IOException e) {
messageList.add("BufferedReader error");
}
String inputLine;
try {
while((inputLine = bReader.readLine()) != null)
{
messageList.add(inputLine);
if(inputLine.equals("close"))
{
close();
}
}
} catch (IOException e) {
messageList.add("Buffered Reader error");
}
}
}
public synchronized void close()
{
messageList.add("****Server closing****");
try {
sSocket.close();
} catch (IOException e) {
messageList.add("Error closing server socket");
}
try {
cSocket.close();
} catch (IOException e) {
messageList.add("Error closing client socket");
}
pWriter.close();
try {
bReader.close();
} catch (IOException e) {
messageList.add("Error closing buffered reader");
}
messageList.add("****It's been fun, but I've got to go.****\n****Server has shut down.****");
System.exit(0);
}
}
GUI:
import java.awt.EventQueue;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.border.EmptyBorder;
import javax.swing.JOptionPane;
import javax.swing.JTextField;
import javax.swing.JButton;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JMenu;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
import java.awt.List;
import java.awt.Toolkit;
#SuppressWarnings("serial")
public class ClientGUI extends JFrame {
private JPanel contentPane;
private JTextField txtEnterTextHere;
private JMenuBar menuBar;
private List messageList;
private JMenu mnOptions;
private JMenu mnHelp;
private JMenuItem mntmStartServer;
private JMenuItem mntmStopServer;
private JMenuItem mntmConnectionInfo;
private JMenuItem mntmEmailDeveloper;
private static String userName;
private ChatServer cServer;
/**
* Launch the application.
*/
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
ClientGUI frame = new ClientGUI();
frame.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
/**
* Create the frame.
*/
public ClientGUI() {
setTitle("Ben's Chat Client");
setResizable(false);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setBounds(100, 100, 450, 300);
menuBar = new JMenuBar();
setJMenuBar(menuBar);
JMenu mnFile = new JMenu("File");
menuBar.add(mnFile);
JMenuItem mntmExit = new JMenuItem("Exit");
mntmExit.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
JOptionPane.showConfirmDialog(null, "Are you sure you want to exit?");
}
});
mnFile.add(mntmExit);
mnOptions = new JMenu("Options");
menuBar.add(mnOptions);
mntmStartServer = new JMenuItem("Start Server");
mntmStartServer.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
ChatServer cServer = new ChatServer(messageList);
cServer.run();
}
});
mnOptions.add(mntmStartServer);
mntmStopServer = new JMenuItem("Stop Server");
mnOptions.add(mntmStopServer);
mntmConnectionInfo = new JMenuItem("Connection Info");
mnOptions.add(mntmConnectionInfo);
mnHelp = new JMenu("Help");
menuBar.add(mnHelp);
mntmEmailDeveloper = new JMenuItem("Email Developer");
mnHelp.add(mntmEmailDeveloper);
contentPane = new JPanel();
contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
setContentPane(contentPane);
contentPane.setLayout(null);
txtEnterTextHere = new JTextField();
txtEnterTextHere.setBounds(10, 220, 334, 20);
txtEnterTextHere.setText("Enter text here...");
contentPane.add(txtEnterTextHere);
txtEnterTextHere.setColumns(10);
JButton btnSend = new JButton("Send");
btnSend.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
messageList.add(userName + ": " + txtEnterTextHere.getText().toString());
}
});
messageList = new List();
btnSend.setBounds(349, 219, 85, 23);
contentPane.add(btnSend);
messageList.setBounds(10, 10, 424, 204);
contentPane.add(messageList);
}
public static String getUsername()
{
return userName;
}
public static void setUsername(String entName)
{
userName = entName;
}
}
Thanks!
It looks like you're starting the server on the Swing thread (see: The Event Dispatch Thread). As soon as you call cServer.run(); in the ActionListener, you are blocking the EDT from doing anything else (such as updating your JFrame and responding to events). Start your server in a background thread instead:
new Thread(new Runnable()
{
#Override
public void run()
{
// start your server
}
}).start();

Why doesn't this client/server program stop?

As I am learning java socket, I've made a functionnal but very simple chat in two frames : one client and one server. The app is only local and works. But it does not stop when I close windows (though I added WindowListener to both frame classes) : what's wrong ?
Don't forget to run the server first, and then the client : both frames will be visibles only after the client connection.
Here is SimpleSocketFrame.java (base class for both frames) :
package com.loloof64.java_se.simple_socket;
import java.awt.GridLayout;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import javax.swing.JFrame;
import javax.swing.JTextArea;
import javax.swing.JTextField;
public abstract class SimpleSocketFrame extends JFrame {
public SimpleSocketFrame() {
setTitle(getFrameTitle());
setLayout(new GridLayout(0, 1));
messageToAddField = new JTextField(30);
messageToAddField.addKeyListener(new KeyAdapter() {
#Override
public void keyReleased(KeyEvent e) {
if (e.getKeyCode() == KeyEvent.VK_ENTER){
if ( ! messageToAddField.getText().isEmpty()) {
addMessage(messageToAddField.getText());
messageToAddField.setText("");
}
}
}
});
printedMessagesArea = new JTextArea(10,30);
printedMessagesArea.setEditable(false);
add(messageToAddField);
add(printedMessagesArea);
pack();
}
protected abstract void addMessage(String s);
protected abstract String getFrameTitle();
private static final long serialVersionUID = -5861605385948623162L;
protected JTextArea printedMessagesArea;
private JTextField messageToAddField;
}
Here is the server app class : SimpleSocketServer.java
package com.loloof64.java_se.simple_socket;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintStream;
import java.net.ServerSocket;
import java.net.Socket;
import javax.swing.JOptionPane;
public class SimpleSocketServer extends SimpleSocketFrame {
public SimpleSocketServer(){
super();
setTitle("Simple Server");
try {
serverSocket = new ServerSocket(12345);
relatedSocket = serverSocket.accept();
outStream = new PrintStream(relatedSocket.getOutputStream());
isr = new InputStreamReader(relatedSocket.getInputStream());
inStream = new BufferedReader(isr);
final InStreamRunnable inStreamRunnable = new InStreamRunnable();
Thread inStreamReaderThread = new Thread(inStreamRunnable);
addWindowListener(new WindowAdapter() {
#Override
public void windowClosing(WindowEvent evt) {
try {
inStream.close();
} catch (IOException e) {
e.printStackTrace();
}
try {
isr.close();
} catch (IOException e) {
e.printStackTrace();
}
outStream.close();
try {
relatedSocket.close();
} catch (IOException e) {
e.printStackTrace();
}
try {
serverSocket.close();
} catch (IOException e) {
e.printStackTrace();
}
inStreamRunnable.stop();
System.exit(0);
}
});
inStreamReaderThread.start();
} catch (IOException e) {
JOptionPane.showMessageDialog(this, "Could not create the server !!!",
"Fatal error", JOptionPane.ERROR_MESSAGE);
System.exit(1);
e.printStackTrace();
}
}
private class InStreamRunnable implements Runnable {
#Override
public void run() {
while (weMustGoOn){
String line;
try {
line = inStream.readLine();
printedMessagesArea.setText(printedMessagesArea.getText()+line+"\n");
} catch (IOException e) {
}
}
}
public void stop(){
weMustGoOn = false;
}
private boolean weMustGoOn = true;
}
#Override
protected void addMessage(String s) {
s = "Serveur> "+s;
outStream.println(s);
printedMessagesArea.setText(printedMessagesArea.getText()+"Client> "+s+"\n");
}
#Override
protected String getFrameTitle() {
return "Simple Server";
}
public static void main(String[] args) {
new SimpleSocketServer().setVisible(true);
}
private static final long serialVersionUID = 4288994465786972478L;
private Socket relatedSocket;
private ServerSocket serverSocket;
private PrintStream outStream;
private InputStreamReader isr;
private BufferedReader inStream;
}
Here is the client class : SimpleSocketClient.java
package com.loloof64.java_se.simple_socket;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintStream;
import java.net.InetAddress;
import java.net.Socket;
import javax.swing.JOptionPane;
public class SimpleSocketClient extends SimpleSocketFrame {
public SimpleSocketClient(){
try {
socket = new Socket(InetAddress.getLocalHost(), 12345);
outStream = new PrintStream(socket.getOutputStream());
isr = new InputStreamReader(socket.getInputStream());
inStream = new BufferedReader(isr);
final InStreamRunnable inStreamRunnable = new InStreamRunnable();
Thread inStreamReaderThread = new Thread(inStreamRunnable);
addWindowListener(new WindowAdapter() {
#Override
public void windowClosing(WindowEvent evt) {
try {
inStream.close();
} catch (IOException e2) {
e2.printStackTrace();
}
try {
isr.close();
} catch (IOException e1) {
e1.printStackTrace();
}
outStream.close();
try {
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
inStreamRunnable.stop();
System.exit(0);
}
});
inStreamReaderThread.start();
} catch (IOException e) {
JOptionPane.showMessageDialog(this, "Could not create the client !!!",
"Fatal error", JOptionPane.ERROR_MESSAGE);
System.exit(1);
e.printStackTrace();
}
}
public static void main(String[] args) {
new SimpleSocketClient().setVisible(true);
}
private class InStreamRunnable implements Runnable {
#Override
public void run() {
while (weMustGoOn){
String line;
try {
line = inStream.readLine();
printedMessagesArea.setText(printedMessagesArea.getText()+line+"\n");
} catch (IOException e) {
}
}
}
public void stop(){
weMustGoOn = false;
}
private boolean weMustGoOn = true;
}
#Override
protected void addMessage(String s) {
s = "Client> "+s;
outStream.println(s);
printedMessagesArea.setText(printedMessagesArea.getText()+s+"\n");
}
#Override
protected String getFrameTitle() {
return "Simple Client";
}
private static final long serialVersionUID = 5468568598525947366L;
private Socket socket;
private PrintStream outStream;
private InputStreamReader isr;
private BufferedReader inStream;
}
The program doesn't stop as you're attempting to close the network input Readers when closing a JFrame, which are blocking indefinitely. BufferedReader and InputStreamReader objects cannot close as the client thread is blocked in this readLine call which is waiting for a response from the server
line = inStream.readLine();
Comment out or remove:
inStream.close();
and
isr.close();
Just closing the Socket stream will suffice.
Aside: When interacting with Swing components for multi-threaded network applications, always use a SwingWorker. SwingWorkers are designed to interact correctly with Swing components.
You should add finally block after try and catch to close the socket and after that you can close your program by system exit method.

Categories