| | |
Issue with MouseListener
Thread Solved |
•
•
Join Date: Sep 2008
Posts: 1,566
Reputation:
Solved Threads: 196
0
#11 22 Days Ago
The error either has to do with memory consistency, or the fact that the InputStream class's read() method blocks while it waits for input (and the read() method gets called multiple times when you keep clicking on the Server's window when it is the client's turn). I'll figure it out soon enough. But if I don't, I think you should read about these avenues as well.
Update:
Ok, so this seems to be the issue: since read() blocks while it waits for input, when the client's receive() method is executed, all subsequent mouse clicks on the client "don't happen" until after the client finishes receiving the data via the read() method. So when you click out of order, you are putting an extra event on the thread which doesn't get executed until after read() is done. What you really want to do is "throw away" the click and pretend it didn't happen at all. But I think you need to multi-thread your application. Hopefully someone else on Daniweb will verify this so that I'm not unintentionally leading you astray, but as of now, I believe this to be accurate.
Update:
Ok, so this seems to be the issue: since read() blocks while it waits for input, when the client's receive() method is executed, all subsequent mouse clicks on the client "don't happen" until after the client finishes receiving the data via the read() method. So when you click out of order, you are putting an extra event on the thread which doesn't get executed until after read() is done. What you really want to do is "throw away" the click and pretend it didn't happen at all. But I think you need to multi-thread your application. Hopefully someone else on Daniweb will verify this so that I'm not unintentionally leading you astray, but as of now, I believe this to be accurate.
Last edited by BestJewSinceJC; 22 Days Ago at 3:28 pm.
Out.
•
•
Join Date: Sep 2008
Posts: 1,566
Reputation:
Solved Threads: 196
1
#13 22 Days Ago
Sorry, took too long and couldn't edit my last post. Update:
Ok, so this seems to be the issue: since read() blocks while it waits for input, when the client's receive() method is executed, all subsequent mouse clicks on the client "don't happen" until after the client finishes receiving the data via the read() method. So when you click out of order, you are putting an extra event on the thread which doesn't get executed until after read() is done. What you really want to do is "throw away" the click and pretend it didn't happen at all. But I think you need to multi-thread your application. Hopefully someone else on Daniweb will verify this so that I'm not unintentionally leading you astray, but as of now, I believe this to be accurate.
This code will demonstrate to you what I'm talking about. If you look at the ClientTurn_flag variable, you'd expect that once you click (which calls receive() and sets ClientTurn_flag to false), the next time you clicked on the client's window, it should print out "wasn't client's turn". However, it doesn't do that, since the read() method is blocking the thread. In fact what *I think* happens is this. Lets say you run the program, then click:
1) Click client's window
-At this point ClientTurn_flag is true.
-client sends it's coordinates to the server.
-client calls receive method and waits for the server to take it's turn. The receive method calls read(), which blocks, so it just sits there waiting for the server to send it data. Now ClientTurn_flag is false, because it is set to false before read() is called.
-it is now the server's turn, and the server is sitting there waiting for you to click on it's window. ServerTurn_flag is true.
2) Click client's window again.
-Since the client is still sitting in the receive() method, which is blocking your thread, the mouse click doesn't happen yet. ClientTurn_flag is still false. Now you can basically think of your stack as looking like this:
first in line => receive() -> read()
next in line (behind both of the above) = mouse listener method.
3) Click server's window. Now you would wish that the client will receive the server's data and then ClientTurn_flag would be set to true. In fact, looking back at my logic, what I think is that after you click the server's window, the server calls its send method. Then the server calls receive() and waits for the client's turn and sets its ServerTurn_flag = false.
-Now, remember that read() was waiting on the client from part 2. Since the server just sent it's input, read() finishes in the client. At the end of read(), ClientTurn_flag = true. So now, in the client, since the next method call on the stack (from clicking on the window) was the mouse listener method, that mouse listener method gets called. But you never clicked anything while it was your turn! The click was done while it was the server's turn.
-After mouse listener method gets called, it calls send(), and it sends the coordinates of the mouse click from when you clicked earlier to the server. This may not cause a problem if the server happens to be waiting to receive, but I'm pretty sure that if you had clicked the client more times, or switched around the ordering of clicking on client and server, it would. You don't want this to happen because the server should always be ready to receive when the client wants to send and vice versa.
Anyway, I spent a good bit of time attempting to figure out and then explain your problem, so I sincerely hope that it is correct. You can test my sample program to confirm that it appears to be correct.. for example, when you click the mouse over and over, you can tell that read() is blocking because the print statements get printed out much later in the program. I believe you can solve your problem by multi-threading your application so that every time a mouse is clicked, it checks (in a separate thread!) to see if it is that Client's/Server's turn, and if not, the method call just returns.
Ok, so this seems to be the issue: since read() blocks while it waits for input, when the client's receive() method is executed, all subsequent mouse clicks on the client "don't happen" until after the client finishes receiving the data via the read() method. So when you click out of order, you are putting an extra event on the thread which doesn't get executed until after read() is done. What you really want to do is "throw away" the click and pretend it didn't happen at all. But I think you need to multi-thread your application. Hopefully someone else on Daniweb will verify this so that I'm not unintentionally leading you astray, but as of now, I believe this to be accurate.
This code will demonstrate to you what I'm talking about. If you look at the ClientTurn_flag variable, you'd expect that once you click (which calls receive() and sets ClientTurn_flag to false), the next time you clicked on the client's window, it should print out "wasn't client's turn". However, it doesn't do that, since the read() method is blocking the thread. In fact what *I think* happens is this. Lets say you run the program, then click:
1) Click client's window
-At this point ClientTurn_flag is true.
-client sends it's coordinates to the server.
-client calls receive method and waits for the server to take it's turn. The receive method calls read(), which blocks, so it just sits there waiting for the server to send it data. Now ClientTurn_flag is false, because it is set to false before read() is called.
-it is now the server's turn, and the server is sitting there waiting for you to click on it's window. ServerTurn_flag is true.
2) Click client's window again.
-Since the client is still sitting in the receive() method, which is blocking your thread, the mouse click doesn't happen yet. ClientTurn_flag is still false. Now you can basically think of your stack as looking like this:
first in line => receive() -> read()
next in line (behind both of the above) = mouse listener method.
3) Click server's window. Now you would wish that the client will receive the server's data and then ClientTurn_flag would be set to true. In fact, looking back at my logic, what I think is that after you click the server's window, the server calls its send method. Then the server calls receive() and waits for the client's turn and sets its ServerTurn_flag = false.
-Now, remember that read() was waiting on the client from part 2. Since the server just sent it's input, read() finishes in the client. At the end of read(), ClientTurn_flag = true. So now, in the client, since the next method call on the stack (from clicking on the window) was the mouse listener method, that mouse listener method gets called. But you never clicked anything while it was your turn! The click was done while it was the server's turn.
-After mouse listener method gets called, it calls send(), and it sends the coordinates of the mouse click from when you clicked earlier to the server. This may not cause a problem if the server happens to be waiting to receive, but I'm pretty sure that if you had clicked the client more times, or switched around the ordering of clicking on client and server, it would. You don't want this to happen because the server should always be ready to receive when the client wants to send and vice versa.
Anyway, I spent a good bit of time attempting to figure out and then explain your problem, so I sincerely hope that it is correct. You can test my sample program to confirm that it appears to be correct.. for example, when you click the mouse over and over, you can tell that read() is blocking because the print statements get printed out much later in the program. I believe you can solve your problem by multi-threading your application so that every time a mouse is clicked, it checks (in a separate thread!) to see if it is that Client's/Server's turn, and if not, the method call just returns.
Java Syntax (Toggle Plain Text)
package game; import java.awt.*; import java.awt.event.*; import java.io.*; import java.net.*; import javax.swing.*; public class Clientms2 extends JFrame implements MouseListener { private static final long serialVersionUID = 1L; JFrame container; static InetAddress address; static Socket s; static String host = "localhost"; static BufferedOutputStream bos; static OutputStreamWriter osw; static BufferedInputStream bis; static InputStreamReader isr; static int port = 5656; static String message; static boolean ClientTurn_flag = true; //static MouseListener l; static int tempx, tempy; static int mouseX, mouseY; static StringBuffer x, y; public Clientms2() { super("Client 1: Player 1"); setSize(400, 400); setDefaultCloseOperation(EXIT_ON_CLOSE); this.setResizable(false); addMouseListener(this); try { address = InetAddress.getByName(host); s = new Socket(address, port); } catch(Exception e){System.out.println("You fail at socket programs sucka!!!");} } public static void main(String args[]) { Clientms2 client = new Clientms2(); client.setVisible(true); } @Override public void mouseClicked(MouseEvent e) { if (ClientTurn_flag){ mouseX = e.getX(); mouseY = e.getY(); send(mouseX, mouseY); System.out.println("End of client's turn, client waiting to receive."); receive(); }else{ System.out.println("Wasn't clients turn"); } } public void receive() { System.out.println("Receive method called, all subsequent clicks on the client's window" + "should now result in seeing 'wasn't client's turn'"); ClientTurn_flag = false; try { do { bis = new BufferedInputStream(s.getInputStream()); isr = new InputStreamReader(bis, "US-ASCII"); } while(isr.ready() == true); x = new StringBuffer(); y = new StringBuffer(); while((tempx = isr.read()) != 13) x.append((char) tempx); String str = x.toString(); mouseX = Integer.parseInt(str); while((tempy = isr.read()) != 13) y.append((char) tempy); str = y.toString(); mouseY = Integer.parseInt(str); ClientTurn_flag=true; } catch (IOException e) { System.out.println("Error in client received"); } System.out.println("Client finished receiving"); ClientTurn_flag= true; } private void send(int xcor, int ycor) { try { bos = new BufferedOutputStream(s.getOutputStream()); osw = new OutputStreamWriter(bos, "US-ASCII"); message = (Integer.toString(xcor)) + (char) 13; osw.write(message); osw.flush(); message = (Integer.toString(ycor)) + (char) 13; osw.write(message); osw.flush(); ClientTurn_flag = false; } catch (IOException e) { e.printStackTrace(); } System.out.println("Client finished sending"); } @Override public void mouseEntered(MouseEvent e) { // TODO Auto-generated method stub } @Override public void mouseExited(MouseEvent e) { // TODO Auto-generated method stub } @Override public void mousePressed(MouseEvent e) { // TODO Auto-generated method stub } @Override public void mouseReleased(MouseEvent e) { // TODO Auto-generated method stub } }
Java Syntax (Toggle Plain Text)
package game; import java.awt.*; import java.awt.event.MouseEvent; import java.awt.event.MouseListener; import java.io.*; import java.net.*; import javax.swing.*; public class Serverms2 extends JFrame implements MouseListener { private static final long serialVersionUID = 1L; JFrame container; static Socket s; static ServerSocket ss; static BufferedOutputStream bos; static OutputStreamWriter osw; static BufferedInputStream bis; static InputStreamReader isr; static StringBuffer x, y; static int port = 5656; static int ID, count = 0; static int tempx, tempy; static int mouseX, mouseY; static String message; static boolean ServerTurn_flag = false; public Serverms2() { super("Server: Player 2"); setSize(400, 400); setDefaultCloseOperation(EXIT_ON_CLOSE); this.setResizable(false); addMouseListener(this); try { ss = new ServerSocket(port); } catch (IOException e1) { e1.printStackTrace(); } } public static void main(String args[]) { Serverms2 server = new Serverms2(); server.setVisible(true); try { s = ss.accept(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } server.receive(); } @Override public void mouseClicked(MouseEvent e) { if (ServerTurn_flag){ mouseX = e.getX(); mouseY = e.getY(); send(mouseX, mouseY); receive(); } else{ System.out.println("Wasn't servers turn."); } } public void receive() { ServerTurn_flag = false; try { bis = new BufferedInputStream(s.getInputStream()); isr = new InputStreamReader(bis, "US-ASCII"); x = new StringBuffer(); y = new StringBuffer(); while((tempx = isr.read()) != 13) x.append((char) tempx); String str = x.toString(); mouseX = Integer.parseInt(str); while((tempy = isr.read()) != 13) y.append((char) tempy); str = y.toString(); mouseY = Integer.parseInt(str); } catch (IOException e) {System.out.println("I hate it when this crap happens.."); } System.out.println("Server done receiving."); ServerTurn_flag = true; } private void send(int xcor, int ycor) { try { bos = new BufferedOutputStream(s.getOutputStream()); osw = new OutputStreamWriter(bos, "US-ASCII"); message = (Integer.toString(xcor)) + (char) 13; osw.write(message); osw.flush(); //System.out.println(message); message = (Integer.toString(ycor)) + (char) 13; osw.write(message); osw.flush(); bos.flush(); //System.out.println(message); } catch (IOException e) { e.printStackTrace(); } } @Override public void mouseEntered(MouseEvent e) { // TODO Auto-generated method stub } @Override public void mouseExited(MouseEvent e) { // TODO Auto-generated method stub } @Override public void mousePressed(MouseEvent e) { // TODO Auto-generated method stub } @Override public void mouseReleased(MouseEvent e) { // TODO Auto-generated method stub } }
Out.
•
•
Join Date: Sep 2008
Posts: 1,566
Reputation:
Solved Threads: 196
1
#14 22 Days Ago
My example was pretty long, but try to grasp the concept and I think you'll be able to complete your program. Again, the basic idea I'm proposing is that you multi-thread your application so that the read() method doesn't block the main thread. I'm not sure of the best way to do this, but I'd first try to create a new Thread in which you'd run the receive() method. Hypothetically, you could also make sure that any time the mouse listener method was called it happened in a different thread, but I don't know how you'd do that (since it depends on an event). So if it was my program I'd try the first option. Anyway I really hope this works out for you. I'm no expert in Socket programming or in multithreaded programming, and everything I said here could be completely wrong. But I know the basic concepts of each, so hopefully that little knowledge will be helpful to you here. Good luck
Last edited by BestJewSinceJC; 22 Days Ago at 4:05 pm.
Out.
1
#15 22 Days Ago
I think you are correct that the behavior did stem from some blocking, but this can still be simplified a great deal to work without a separate listening thread.
Here's a re-wired version of the same that behaves itself. It's worth noting that these two versions only differ in what kind of socket is created to make one the "server". They could be coalesced to a single class. (It's also a quickly slapped together modification that doesn't properly handle exceptions or shut down properly and close io streams
)
Here's a re-wired version of the same that behaves itself. It's worth noting that these two versions only differ in what kind of socket is created to make one the "server". They could be coalesced to a single class. (It's also a quickly slapped together modification that doesn't properly handle exceptions or shut down properly and close io streams
) Java Syntax (Toggle Plain Text)
package game; import java.awt.*; import java.awt.event.*; import java.io.*; import java.net.*; import javax.swing.*; public class Clientms2 extends JFrame implements MouseListener { private static final long serialVersionUID = 1L; JFrame container; InetAddress address; Socket s; String host = "localhost"; PrintWriter out = null; BufferedReader in = null; int port = 5656; String message; int mouseX, mouseY; boolean myTurn = true; JTextArea status = new JTextArea(); public Clientms2() { super("Client 1: Player 1"); setDefaultCloseOperation(EXIT_ON_CLOSE); //this.setResizable(false); addMouseListener(this); status.addMouseListener(this); add(status); pack(); setSize(400, 400); } public static void main(String args[]) { Clientms2 client = new Clientms2(); client.setVisible(true); client.run(); } public void run() { try { address = InetAddress.getByName(host); s = new Socket(address, port); // establish streams one time out = new PrintWriter(s.getOutputStream(), true); in = new BufferedReader(new InputStreamReader( s.getInputStream())); // start processing myTurn = true; String input = ""; while ((input = in.readLine()) != null) { if (!myTurn) { process(input); } } } catch (Exception e) { e.printStackTrace(); } } @Override public void mouseClicked(MouseEvent e) { if (myTurn) { mouseX = e.getX(); mouseY = e.getY(); send(mouseX, mouseY); status.append("End of client's turn, client waiting to receive.\n"); myTurn = false; } } public void process(String input) { try { String[] coordStr = input.split(","); if (coordStr.length == 2) { mouseX = Integer.parseInt(coordStr[0]); mouseY = Integer.parseInt(coordStr[1]); status.append("received " + mouseX + " " + mouseY + "\n"); myTurn = true; } } catch (Exception e) { e.printStackTrace(); } } private void send(int xcor, int ycor) { try { message = xcor + "," + ycor; out.println(message); } catch (Exception e) { e.printStackTrace(); } } @Override public void mouseEntered(MouseEvent e) { // TODO Auto-generated method stub } @Override public void mouseExited(MouseEvent e) { // TODO Auto-generated method stub } @Override public void mousePressed(MouseEvent e) { // TODO Auto-generated method stub } @Override public void mouseReleased(MouseEvent e) { // TODO Auto-generated method stub } }
Java Syntax (Toggle Plain Text)
package game; import java.awt.*; import java.awt.event.MouseEvent; import java.awt.event.MouseListener; import java.io.*; import java.net.*; import javax.swing.*; public class Serverms2 extends JFrame implements MouseListener { private static final long serialVersionUID = 1L; JFrame container; Socket s; ServerSocket ss; PrintWriter out = null; BufferedReader in = null; int port = 5656; int mouseX, mouseY; String message; boolean myTurn = false; JTextArea status = new JTextArea(); public Serverms2() { super("Server: Player 2"); setDefaultCloseOperation(EXIT_ON_CLOSE); //this.setResizable(false); addMouseListener(this); status.addMouseListener(this); add(status); pack(); setSize(400, 400); try { ss = new ServerSocket(port); } catch (IOException e1) { e1.printStackTrace(); } } public void run() { try { s = ss.accept(); out = new PrintWriter(s.getOutputStream(), true); in = new BufferedReader(new InputStreamReader( s.getInputStream())); myTurn = false; String input = ""; while ((input = in.readLine()) != null) { if (!myTurn) { process(input); } } } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } public static void main(String args[]) { Serverms2 server = new Serverms2(); server.setVisible(true); server.run(); } @Override public void mouseClicked(MouseEvent e) { if (myTurn) { mouseX = e.getX(); mouseY = e.getY(); send(mouseX, mouseY); status.append("End of server's turn, waiting to receive.\n"); myTurn = false; } } private void process(String input) { try { String[] coordStr = input.split(","); if (coordStr.length == 2) { mouseX = Integer.parseInt(coordStr[0]); mouseY = Integer.parseInt(coordStr[1]); myTurn = true; status.append("received " + mouseX + " " + mouseY + "\n"); } } catch (Exception e) { e.printStackTrace(); } } private void send(int xcor, int ycor) { try { message = xcor + "," + ycor; out.println(message); } catch (Exception e) { e.printStackTrace(); } } @Override public void mouseEntered(MouseEvent e) { // TODO Auto-generated method stub } @Override public void mouseExited(MouseEvent e) { // TODO Auto-generated method stub } @Override public void mousePressed(MouseEvent e) { // TODO Auto-generated method stub } @Override public void mouseReleased(MouseEvent e) { // TODO Auto-generated method stub } }
Last edited by Ezzaral; 22 Days Ago at 6:23 pm.
•
•
Join Date: Sep 2008
Posts: 1,566
Reputation:
Solved Threads: 196
0
#16 22 Days Ago
Well, thank god that somebody else stepped up, because I was getting quite frustrated and it isn't even my program. Haha. Although after a quick look I don't see why your version is any different than mine was, but I suppose it is those two while loops that truly make the difference. But no need to explain unless the OP is curious - I'll take a look at it when I get up the effort to look at this thing without getting frustrated again.
Last edited by BestJewSinceJC; 22 Days Ago at 8:27 pm.
Out.
•
•
Join Date: Nov 2009
Posts: 12
Reputation:
Solved Threads: 0
0
#17 22 Days Ago
OMG!! You guys are awesome!!!!
Looll! I did sorta suspect that the mouselistener kept getting called, and that out-of-turn co-ords were stored somewhere, but just weren't sent until receive() completed. That was why I added the removeMouseListener method. I thought that would disable the mouselistener after one set of co-ords were sent out, and since I didn't add it again until after the receive() method, I figured that the intermediate out-of-turn clicks would effectively be "thrown away". But, I guess I was mistaken. Anyways, thanks again!! I can now finally move on with the rest of my program.
Java Syntax (Toggle Plain Text)
while(true) System.out.println("Thaaaaaaaaaank you!!!");
Looll! I did sorta suspect that the mouselistener kept getting called, and that out-of-turn co-ords were stored somewhere, but just weren't sent until receive() completed. That was why I added the removeMouseListener method. I thought that would disable the mouselistener after one set of co-ords were sent out, and since I didn't add it again until after the receive() method, I figured that the intermediate out-of-turn clicks would effectively be "thrown away". But, I guess I was mistaken. Anyways, thanks again!! I can now finally move on with the rest of my program.
•
•
Join Date: Sep 2008
Posts: 1,566
Reputation:
Solved Threads: 196
0
#18 22 Days Ago
That is actually good logic - but it assumes that the MouseListener wouldn't get re-added due to the method calls being blocked/having to wait for receive, so it probably runs into the same problem as the variable does. Although I'm not sure and honestly don't feel like investigating. But I'm glad you have it working now, wish I could've been of better assistance.
PS mark solved
PS mark solved
Last edited by BestJewSinceJC; 22 Days Ago at 9:01 pm.
Out.
![]() |
Similar Threads
- Windows Explorer Issue: my "Address" bar is gone, how do I get it back? (Windows NT / 2000 / XP)
- Power boot up issue (Motherboards, CPUs and RAM)
- Getting Windows to see a SATA drive (Storage)
- BitchX + Terminal issue (Mac Software)
- Kernel Version of Mandrake and error message (*nix Software)
- Memory Issue's! Please Help!! (Motherboards, CPUs and RAM)
- Internet Explorer Connection Issue (Web Browsers)
- Netgear router issue...read this if you have one (Networking Hardware Configuration)
Other Threads in the Java Forum
- Previous Thread: Final Year Project! Please help!
- Next Thread: Java object persistance
| Thread Tools | Search this Thread |
911 actionlistener addressbook android api append applet application array arrays automation binary blackberry block bluetooth character chat class client code component consumer csv database desktop developmenthelp eclipse error fractal ftp game givemetehcodez graphics gui html ide image integer j2me j2seprojects japplet java javaarraylist javac javaee javaprojects jni jpanel julia lego linked linux list loops mac map method methods mobile netbeans newbie number objects online oriented panel printf problem program programming project projects properties recursion replaydirector reporting researchinmotion rotatetext rsa scanner se server set singleton sms sort sql string swing test textfields threads time title tree tutorial-sample ubuntu update windows working






