I'm very new to Java here. I have a program which acts like a calculator between client and server. the client will enter their function like this (+ 1 2). But now Im giving it a GUI interface. How do i pass the user input from GUI to client console then pass it to the server to calculate and then displaying it back to the UI? i just need something simple.
client
import java.io.*;
import java.net.Socket;
import java.util.Scanner;
import java.awt.*; // using AWT containers and components
import java.awt.event.*; // using AWT events and listener interfaces
import javax.swing.*;
public class mathClient extends JFrame implements ActionListener {
private int count = 0;
private JFrame frame;
private JPanel panel;
private JLabel lblInput;
private JLabel lblOutput;
private JTextField tfInput;
private JTextField tfOutput;
/** The entry main() method */
public static void main(String[] args) throws Exception {
// Invoke the constructor to setup the GUI, by allocating an instance
mathClient app = new mathClient();
}
public void actionPerformed(ActionEvent event){
try{
Socket clientSocket = new Socket("localhost", 50000);
BufferedReader inFromServer = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
DataOutputStream outToServer = new DataOutputStream(clientSocket.getOutputStream());
PrintWriter print = new PrintWriter(clientSocket.getOutputStream(), true);
String input;
String output;
//String input;
while(true){
//System.out.println("Please enter your function and numbers:");
input = tfInput.getText();
print.println(input);
if(input.equals("disconnect")){
break;
}
output = inFromServer.readLine();
System.out.println(output);
tfOutput.setText(output);
}
clientSocket.close();
}
catch (Exception e)
{
}
}
public mathClient()
{
Container contentPane = getContentPane();
contentPane.setLayout(new BorderLayout());
JFrame frame = new JFrame("Calculator");
JPanel panel = new JPanel();
JLabel lblInput = new JLabel("Input: ");
JLabel lblOutput = new JLabel("Output: ");
JTextField tfInput = new JTextField();
tfInput.setEditable(true);
// tfInput.addActionListener();
JTextField tfOutput = new JTextField();
tfOutput.setEditable(false);
JButton btnCalculate = new JButton("Calculate");
btnCalculate.addActionListener(this);
frame.add(panel);
panel.add(lblInput);
panel.add(tfInput);
panel.add(lblOutput);
panel.add(tfOutput);
panel.add(btnCalculate);
tfInput.setPreferredSize(new Dimension(200, 30));
tfOutput.setPreferredSize(new Dimension(200, 30));
frame.pack();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(230,250);
frame.setResizable(false);
frame.setVisible(true);
}
}
Server
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Scanner;
// Takes in a mathematical operation and the operands from a client and returns the result
// Valid operations are add, sub, multiply, power, divide, remainder, square
public class mathServer
{
public static void main(String [] args) throws IOException
{
ServerSocket welcomeSocket = new ServerSocket(50000); //put server online
while(true)
{
System.out.println("Waiting for connection...");
Socket connectionSocket = welcomeSocket.accept(); //open server to connections
System.out.println("Connection accepted");
process(connectionSocket); //process accepted connection
System.out.println("Connection closed");
}
}
//BufferedReader(Reader r)
static void process(Socket welcomeSocket) throws IOException
{
InputStream in = welcomeSocket.getInputStream();
BufferedReader buffer = new BufferedReader(new InputStreamReader(in));
OutputStream out = welcomeSocket.getOutputStream();
PrintWriter print = new PrintWriter(out, true);
String input = buffer.readLine(); //get user input from client
while(input != null && !input.equals("disconnect")) //check for input, if bye exit connection
{
int answer = operate(input); //perform desired operation on user input
print.println(answer); //print out result
input = buffer.readLine(); //get next line of input
}
welcomeSocket.close();
}
//Talk to the client
static int operate(String s)
{
System.out.println(s); //check if same as client input
Scanner scanner = new Scanner(s);
char option = scanner.next().charAt(0); //gets desired operation
System.out.println(option); //checks for correct operation
switch (option) {
case '+':
return (scanner.nextInt() + scanner.nextInt());
case '-':
return (scanner.nextInt() - scanner.nextInt());
case '*':
return (scanner.nextInt() * scanner.nextInt());
case '^':
return (int) Math.pow(scanner.nextInt(), scanner.nextInt());
case '/':
return scanner.nextInt() / scanner.nextInt();
case '%':
return scanner.nextInt() % scanner.nextInt();
case 's':
return (int) Math.pow(scanner.nextInt(), 2);
default:
return (int) Math.pow(scanner.nextInt(), 3);
}
}
}
One of the problems is an NullPointerException in actionPerformed(). However it is not visible as you have an empty catch block. You should never have empty catch blocks. Change it to:
catch (Exception e) {
e.printStackTrace();
}
The members tfInput and tfOutput are null in actionPerformed() as they are never initialized. The constructor mathClient() allocates local variables JTextField tfInput and JTextField tfInput and overshadows the relevant members.
Other than the endless while loop there are several other immediate problems. You should not block Swing's Event Dispatch Thread with a socket. Consider using an auxiliary thread or a SwingWorker.
See Concurrency in Swing for details and examples.
Related
I am trying to write a server application in java and creating a vector v1 to store all the sockets that hit the server.
Next i made an arraylist where i stored all my Client sockets as objects and then created a JCheckBox array where I loop it to add checkbox to the JPanel controlpanel which was initiated in the class contructor but something seems to be going wrong and i can't see any checkbox.
import java.util.*;
import java.net.*;
import javax.swing.*;
import java.awt.event.*;
import java.io.*;
import java.awt.*;
class server extends JFrame implements ActionListener {
JTextArea t1;
PrintWriter pw;
JButton b1, b2;
static Vector v1 = new Vector();
static ArrayList checks = new ArrayList();
static JPanel controlpanel;
server() {
setLayout(new FlowLayout());
t1 = new JTextArea();
add(t1);
b1 = new JButton("Send to All");
b2 = new JButton("Send");
//b1.addActionListener(this);
//b2.addActionListener(this);
add(b2, BorderLayout.SOUTH);
add(b1, BorderLayout.NORTH);
b1.addActionListener(this);
b2.addActionListener(this);
controlpanel = new JPanel();
controlpanel.setVisible(true);
add(controlpanel);
}
public void actionPerformed(ActionEvent ae) {
String m = t1.getText();
if (ae.getSource() == b1) {
try {
Iterator t2 = v1.iterator();
while (t2.hasNext()) {
Socket s = (Socket) t2.next();
pw = new PrintWriter(s.getOutputStream(), true);
pw.println(m);
pw.flush();
System.out.println("send" + m);
}
} catch (Exception e) {
}
}
if (ae.getSource() == b2) {
try {
Iterator itr = checks.iterator();
while (itr.hasNext()) {
Socket schecked = (Socket) itr.next();
pw = new PrintWriter(schecked.getOutputStream(), true);
pw.println(m);
pw.flush();
System.out.println("sent " + m);
}
} catch (Exception e) {
}
}
t1.setText("");
}
public static void main(String z[]) {
try {
new server().setVisible(true);
ServerSocket s = new ServerSocket(2000);
while (true) {
System.out.println("waiting...");
Socket c = s.accept();
// System.out.print(c);
v1.add(c);
for (int i = 0; i < v1.size(); i++) {
checks.add(v1.get(i));
// checks[i].setText()=v1[i];
}
JCheckBox checkbox[] = new JCheckBox[checks.size()];
for (int i = 0; i < checks.size(); i++) {
// Object o=checks.get(i);
checkbox[i] = new JCheckBox();
// checkbox[i].setText()=checks.get(i).name;
controlpanel.add(checkbox[i]);
checkbox[i].setSelected(true);
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
As you are adding UI elements after the JFrame has been made visible, you need to call revalidate() on the panel. Also you should never add directly from a thread which is not the Event Dispatch Thread. Finally, it appears every time a new client connects, you're going to re-add all the checkbox you already have added, plus one (i.e. when the first client connects you will have 1 checkbox, when the second connects you'll have 1 + 2 = 3, when the third connects you'll have 1 + 2 + 3 = 6, etc.).
I strongly suggests you mentally run through your code, instruction by instruction, to see what happens. Alternatively, if you're using a decent IDE, you can step through the code in the debugger and inspect the content of controlPanel. If you're not using an IDE... you should.
I don't quite understand what you need check[] and v1[] for but assuming that you do need them, instead of maintaining three arrays you can define a class containing a variable for a check, one for a v1, and one for a checkbox, and maintain a single array of instances of such objects.
I am trying to develop a GUI based chat-server.I built a client class which has the code to generate the GUI for the client and the methods to write to the server and then to read from the server.The client class writes the message to the buffer of ServerSocket when the send button is clicked.
But the problem is that,after executing more than one client when i write message in the JTextField of a client GUI and then click send then the message gets visible only in the JTextArea of that particular instance of client while JTextArea of other instances of client remain empty i.e no updation takes place in them.
I noticed in the console that JVM puts the instances of the client classes in EventQueue.
I want that updation should take place in every JTextArea of each client's instance.Can somebody help me to achieve this ?
Client Code
import java.io.*;
import java.net.*;
import java.util.*;
import java.awt.*;
import java.awt.event.*;
import java.io.*;
import javax.swing.*;
import javax.swing.border.EmptyBorder;
class TestClient88 implements ActionListener
{
Socket s;
DataOutputStream dout;DataInputStream din;BufferedReader br;
static String nameOfClient=null;
static String message=null;
JFrame frame;
JTextArea textArea;
JTextField textField;
JButton button;
public TestClient88 ()
{ //just at the time of login
System.out.println("enter ur name");
nameOfClient=new Scanner(System.in).nextLine();
frame=new JFrame(nameOfClient);
textArea=new JTextArea();
textArea.setBounds(0,0,500,400);
textArea.setEditable(false);
textField=new JTextField();
textField.setBounds(0,405,350,30);
// textField.setText("test");
button=new JButton("send");
button.setBounds(355,405,100,30);
// button.addActionListener(this);
button.addActionListener(this);
frame.add(textField);
frame.add(textArea);
frame.add(button);
frame.setSize(500,500);
frame.setLayout(null);
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
try{
s=new Socket("localhost",10);
System.out.println(s);
din=new DataInputStream(s.getInputStream());
dout=new DataOutputStream(s.getOutputStream());
br=new BufferedReader(new InputStreamReader(System.in));//to put the name of client in the server socket
}catch(Exception e){}
}
public void actionPerformed(ActionEvent ae)
{
message=textField.getText();
System.out.println("message is "+message);
textField.setText("");
try{
clientchat();
}catch(Exception e){}
}
public void clientchat() throws IOException
{ // //receiving thread to receive message from server
System.out.println("after start "+Thread.currentThread().getName()); //Main thread
String s1=null;
s1=message;
System.out.println("s1 is "+s1);
try{
dout.writeUTF(nameOfClient+" : " +s1);
message=null;
dout.flush();
// Thread.sleep(20000);
String s2=din.readUTF();
System.out.println("message sent from server is "+ s2);
textArea.append(s2+"\n");
}catch(Exception e){}
}
public static void main(String ar[])
{
new TestClient88();
}
}
Server Code
import java.io.*;
import java.net.*;
import java.util.*;
public class Myserver1
{
ArrayList al=new ArrayList();ServerSocket ss;Socket s;
// static ArrayList clientsList=new ArrayList();
static int count;
ObjectInputStream oin;
public Myserver1()
{
try{
ss=new ServerSocket(10);
System.out.println("server socket is "+ss);
while(true)
{
s=ss.accept();//waits for the client socket
System.out.println("client connected");
System.out.println("mike testing");
al.add(s);
Iterator i=al.iterator();
while(i.hasNext())
{
System.out.println("inside while");
System.out.println(i.next());
}
System.out.println("startting server thread ");
Runnable r=new MyThread(s,al);
Thread t=new Thread(r);
t.start();
}
}catch(Exception e){}
}
public static void main(String ar[])
{
new Myserver1();
}
}
class MyThread implements Runnable
{
Socket s;ArrayList al;
MyThread(Socket s,ArrayList al)
{
this.s=s;
this.al=al;
}
public void run()
{
String s1;int i=0;
try{
DataInputStream din=new DataInputStream(s.getInputStream());
do{
s1=din.readUTF();//message of each client
System.out.println(s1);
if(!s1.equals("stop"))
{
tellEveryone(s1);
}
else
{
DataOutputStream dout=new DataOutputStream(s.getOutputStream());
dout.writeUTF(s1);
dout.flush();
al.remove(s);//logging out a client from the server.
}
}while(!s1.equals("stop"));
}catch(Exception e){}
}
public void tellEveryone(String s1)
{
Iterator i=al.iterator();
while(i.hasNext())
{
try{
Socket sc=(Socket)i.next();
DataOutputStream dout=new DataOutputStream(sc.getOutputStream());
dout.writeUTF(s1);
dout.flush();
// System.out.println("client");
}catch(Exception e){}
}
}
}
I am working on project "Distributed Web Crawler using Java RMI".
The web crawls the pages and displays the URLs on two consoles-- a client one and a server one.
My problem is that I have to read these URLs from the console and display it under a Text Area in a window. I have tried a lot but the URLs are not getting displayed in Text Area.
However they were getting displayed on the console.
My code is:
import java.net.*;
import java.io.*;
import java.util.Date;
import java.io.File;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import java.nio.channels.ReadableByteChannel;
import java.nio.channels.Channels;
import java.rmi.*;
import java.util.*;
import java.awt.*;
import javax.swing.*;
import java.awt.event.*;
class UCDemo implements ActionListener {
static String dispServerURL;
JFrame f1;
JPanel p1;
JLabel l1;
JLabel l2;
JTextField t1;
JTextArea t2;
JButton b1;
public void showFrame() {
f1 = new JFrame("Web Crawler");
p1 = new JPanel();
f1.setSize(7000, 7000);
f1.setVisible(true);
f1.setBackground(Color.pink);
f1.getContentPane().add(p1);
l1 = new JLabel("Enter seed URL");
t1 = new JTextField(100);
b1 = new JButton("Start");
l2 = new JLabel("Result");
t2 = new JTextArea(200, 200);
p1.add(l1);
p1.add(t1);
p1.add(b1);
p1.add(l2);
p1.add(t2);
b1.addActionListener(this);
}
public void actionPerformed(ActionEvent ae) {
try {
DispServerIntf dispServerIntf = (DispServerIntf) Naming.lookup(dispServerURL);
if (ae.getSource() == b1) {
String n1, k;
InputStreamReader ir = new InputStreamReader(System.in);
n1 = t1.getText();
int c = 0;
Document document = null;
URL hp = new URL(n1);
URLConnection hpcon = hp.openConnection();
try {
document = Jsoup.parse(hp, 3000);
} catch (IOException e) {
e.printStackTrace();
}
for (Element element : document.getElementsByTag("a")) {
c++;
ReadableByteChannel rbc = Channels.newChannel(hp.openStream());
FileOutputStream fos = new FileOutputStream("te.html");
fos.getChannel().transferFrom(rbc, 0, Long.MAX_VALUE);
if (c <= 7) {
Document doc_tmp = null;
URL hp_tmp = new URL(element.attr("href"));
t2.setText("" + hp_tmp);
URLConnection hpcontmp = hp_tmp.openConnection();
/**
* try { doc_tmp=Jsoup.parse(hp_tmp,3000); }
* catch(IOException e) {e.printStackTrace(); } for
* (Element ele: doc_tmp.getElementsByTag("a")) {
* System.out.println(ele.attr("href")); }
**/
ReadableByteChannel rbc_tmp = Channels.newChannel(hp_tmp.openStream());
FileOutputStream fos_tmp = new FileOutputStream("te" + c + ".html");
fos_tmp.getChannel().transferFrom(rbc_tmp, 0, Long.MAX_VALUE);
} else {
dispServerIntf.send(element.attr("href"));
}
}
/**
* BufferedReader in=new BufferedReader(new
* InputStreamReader(hpcon.getInputStream())); String inputline;
* while((inputline=in.readLine())!=null)
* System.out.println(inputline); in.close();
**/
}
} catch (Exception e) {
}
}
public static void main(String args[]) {
dispServerURL = "rmi://" + args[0] + "/DispServer";
new UCDemo().showFrame();
}
}
One problem is that you are doing all the work in a loop on the AWT thread (the "event dispatch thread") within the actionPerformed method, and updating the GUI in that loop.
This means that the GUI will not be updated properly (because the thread that updates the GUI is busy doing the HTML parsing work, and does not become free to process GUI events). You probably need to do the main loop in a separate thread, then update the GUI in the AWT thread using invokeLater().
See:
this tutorial, for example,
and the linked introduction to threading in Swing.
The official Swing Java Tutorial on this topic, which assumes you have read...
...the Concurrency lesson
Also, you always set the text to a single value, so you would only see the latest URL, not a list of them:
t2.setText("" + hp_tmp);
I try to build server that could talk with several clients at the same time.
But there are some problems with the thread, and the code doesn't work well.
Could you tell me what is wrong with the thread part? Thank you very much.
public class ServerMulti extends JFrame implements ActionListener{
private static final int PORT = 60534;
private JTextField textField = new JTextField();
private static JTextArea textArea = new JTextArea();
private JButton button = new JButton();
public static ServerSocket server;
public static Socket socket;
public static BufferedReader in;
public static PrintWriter out;
public ServerMulti(){
/*
* build up GUI
*/
setTitle("Server Multi");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setSize(300,400);
setBackground(Color.white);
setLayout(new BorderLayout());
button.setText("Send");
button.setSize(300, 50);
textField.setText("Type here");
textArea.setSize(300, 50);
add(textField, BorderLayout.NORTH);
add(new JScrollPane(textArea), BorderLayout.CENTER);
add(button, BorderLayout.SOUTH);
setLocation(300, 100);
button.addActionListener(this);
setVisible(true);
}
/*
* print out the information that need to sent to clients
*
*/
public void actionPerformed(ActionEvent e) {
textArea.append(textField.getText()+"\n");
out.println(textField.getText());
textField.setText("");
}
public static void main(String[] args) throws IOException{
new ServerMulti();
//build up the socket and server
try{
server = new ServerSocket(PORT);
socket = server.accept();
in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
out = new PrintWriter(socket.getOutputStream());
textArea.append("Connected. "+" Port: " + PORT + "\n");
while(true){
worker w = new worker();
Thread t = new Thread(w);
t.start();
}
}catch (IOException e) {
System.out.println("Accept failed:" +PORT);
System.exit(-1);
}
}
//to the same server, different sockets are created connecting to different client
public static class worker implements Runnable{
public void run() {
String msg;
/*
* the "in.readLine()" give the data only once
* 1. so we save the information to a String from the socket
* 2. Then sent out a feedback to client, through socket
* 3. print out the String we just collected
*/
while(true){
try {
msg = in.readLine();
out.println("Server received : " + msg);
textArea.append(msg+"\n");
} catch (IOException e) {
System.out.println("Fail");
e.printStackTrace();
}
}
}
}
}
There are a couple of problems with this, but in terms of multithreading the server: ServerSocket.accept() blocks until a new client attempts to connect. In your code this only happens once; so only one client will be accepted. The layout should instead be something like this:
ServerSocket ss = new ServerSocket(PORT);
while (LISTENING) {
Socket sock = ss.accept();
Handler handler = new Handler(sock);
new Thread(handler).start();
//With the LISTENING variable dealt with as well
}
Here the class Handler should be a Runnable class that deals with the socket on another thread. The while loop can then go back and accept a new connection.
I have a program which asks you for your first name and second name. I used OutputStream to save the first name in a file stored in the workspace. I use a BufferedReader to read the file but I'm trying to get it so if the person clicks yes on the JOptionPane.YES_NO_DIALOG, it uses the name in the file! I've tried doing and if Statement that said if JOptionPane... then text.setText(savedName), but it just comes out as "Welcome null null"
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.io.*;
public class BingoHelper extends JFrame implements WindowListener, ActionListener{
JTextField text = new JTextField();
//JLabel bg = new JLabel("helo");
private JButton b; {
b = new JButton("Click to enter name");
}
JPanel pnlButton = new JPanel();
public static String fn;
public static String sn;
public static int n;
File f = new File("test.txt");
public void actionPerformed (ActionEvent e){
Object[] yesNo = {"Yes",
"No",};
n = JOptionPane.showOptionDialog(null,"Would you like to use previously entered data?","Welcome Back?",JOptionPane.YES_NO_OPTION,JOptionPane.QUESTION_MESSAGE, null, yesNo,yesNo[1]);
if (n == JOptionPane.NO_OPTION){
for(fn=JOptionPane.showInputDialog("What is your first name?");!fn.matches("[a-zA-Z]+");fn.isEmpty()){
JOptionPane.showMessageDialog(null, "Alphabet characters only.");
fn=JOptionPane.showInputDialog("What is your first name?");
}
for(sn=JOptionPane.showInputDialog("What is your second name?");!sn.matches("[a-zA-Z]+");sn.isEmpty()){
JOptionPane.showMessageDialog(null, "Alphabet characters only.");
sn=JOptionPane.showInputDialog("What is your second name?");
}
}
//JOptionPane.showMessageDialog(null, "Welcome " + fn + " " + sn + ".", "", JOptionPane.INFORMATION_MESSAGE);
text.setText("Welcome " + fn + " " + sn + ".");
b.setVisible(false);
b.setEnabled(false);
text.setVisible(true);
text.setBounds(140,0,220,20);
text.setHorizontalAlignment(JLabel.CENTER);
text.setEditable(false);
text.setBackground(Color.YELLOW);
pnlButton.setBackground(Color.DARK_GRAY);
writeToFile();
//bg.setVisible(true);
}
private void writeToFile() {
String nameToWrite = fn;
OutputStream outStream = null;
try {
outStream = new FileOutputStream(f);
outStream.write(nameToWrite.getBytes());
BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream(f)));
String savedName = br.readLine();
//System.out.println(savedName);
br.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
if (null != outStream) {
try {
outStream.close();
} catch (IOException e) {
// do nothing
}
}
}
}
When you use JOptionPane with your own options JOptionPane will return the index of the option select by the user...
That is, in your case, if the user selects "Yes", then JOptionPane will return 0 or if the user selects "No", it will return 1
So, instead of using JOptionPane.NO_OPTION you need use 1, for example...
Object[] yesNo = {"Yes",
"No",};
n = JOptionPane.showOptionDialog(null,"Would you like to use previously entered data?","Welcome Back?",JOptionPane.YES_NO_OPTION,JOptionPane.QUESTION_MESSAGE, null, yesNo,yesNo[1]);
if (n == 1){
//...
}
I would also, strongly, encourage you to avoid using static field references in this context as it may result in unexpected behaviour if you ever get more then one instance of the class running ;)