Join 300,443 Java Programmers for FREE! Get instant access to thousands of Java experts, tutorials, code snippets, and more! There are 1,516 people online right now. Registration is fast and FREE... Join Now!
I'm trying to implement an ActionListener in a simple client with only a JavaTextField and JavaTextArea
Basically, what I've come to is that the ActionListener dies if there's a Try/Catch in it. It doesn't even matter what's in the Try/Catch.
I commented out everything inside and had it try just writing to the textarea(cliTextArea) from the textfield(cliTextField) and it would freeze up when I hit enter. When I took out the try/catch block it would run just fine.
It also stops if I remove the try/catch block, when it gets String cliString = _input.readLine(); But with the try/catch and nothing else but cliTextArea.append(cliUserInput.getText().toString()); it still doesn't run. I don't think the _input.readLine() is what's killing it.
Anyway, enough explaining. Here's the code that I think matters. If anyones curious, _input is a BufferedReader, and _output is a PrintWriter.
You should never perform I/O operation in an actionPerformed routine These are thread fired for an event and they should operate quickly and surely not wait for another user action you would just freeze all other GUI operations
No no, Tanira...you can't put try/catch around a method.
And pbl, how are we supposed to do I/O with a GUI if we can't use it in the actionPerformed method? It seems that we would need to perform something on an action of the user...but I can't think of a way to do it other than putting it in the listener.
This post has been edited by Locke: 6 Jul, 2009 - 10:18 PM
No no, Tanira...you can't put try/catch around a method.
And pbl, how are we supposed to do I/O with a GUI if we can't use it in the actionPerformed method? It seems that we would need to perform something on an action of the user...but I can't think of a way to do it other than putting it in the listener.
You're right and being 3 am I'm not too surprised I missed that. >.>
I'm guessing you also can't add throws declaration to actionPerformed either?
This post has been edited by Tanira: 6 Jul, 2009 - 10:54 PM
I created a Packet class that will grab the information I want to send(and I can use this for other IO instances too, yay) which in this case is just a string from the text field.
New code is working:
CODE
private class ButtonListener implements ActionListener { public void actionPerformed(ActionEvent e) {
//get command from command line
cliTextArea.append("Creating packet." + '\n'); Packet packet = new Packet(_output, "string", cliUserInput.getText().toString()); Thread sendPacket = new Thread(packet); sendPacket.start(); cliUserInput.setText(""); } }
This brings up another question though. This fires off a new packet on a thread. Theoretically every time it runs it creates a new packet. The run method of Packet is just this:
CODE
public void run() { _write.print(this); }
I'm working on this right now. After it sends the full method is finished. Does it automatically destruct or do I need to tell it to?
And um, can anyone remind me how if I need to destruct it?
And pbl, how are we supposed to do I/O with a GUI if we can't use it in the actionPerformed method? It seems that we would need to perform something on an action of the user...but I can't think of a way to do it other than putting it in the listener.
You can perform a single I/O operations like writting a record to a log file or accessing a database but not an operation which depends on user intercation/
CODE
static void ActionPerformed(ActionEvent e) { .... Thread t = new ClassToDoIO(what do write); t.start(); .... }
class ClassToDoIO extends Thread { // instance variables to hol;d what to do File... Record... ClassToDoIO(what to write) { // save what to do } public void run() { do the I/O } }
This post has been edited by pbl: 7 Jul, 2009 - 03:39 PM
You can perform a single I/O operations like writting a record to a log file or accessing a database but not an operation which depends on user intercation/
That makes sense. So you just put the I/O operation in a separate thread, so that uhhhh......wait, I really don't get it. The listener will still fire events, still triggering the actionPerformed() method to be invoked, still triggering the thread you used to be activated. So...what exactly did that do?
I guess I just don't see the point of putting it in a new thread, since it would still finish just the same, right?
(sorry, but I don't have a lot of experience with multithreaded applications)
You can perform a single I/O operations like writting a record to a log file or accessing a database but not an operation which depends on user intercation/
That makes sense. So you just put the I/O operation in a separate thread, so that uhhhh......wait, I really don't get it. The listener will still fire events, still triggering the actionPerformed() method to be invoked, still triggering the thread you used to be activated. So...what exactly did that do?
I guess I just don't see the point of putting it in a new thread, since it would still finish just the same, right?
(sorry, but I don't have a lot of experience with multithreaded applications)
No you start another thread every time The other thread starts The ActionListener and exit finishing its thread The new Thread continue
Another alternative is to have a thread that waits for messages from the ActionListener
public void run() { // loop waiting for question from main app for(;;) { // test if new question if(question != null) { String answer = JOptionPane.......question question = null; father.thisIsAnswer(answer); } else { try { Thread.sleep(500L); } catch(Exception e) {} } } // infinite for() loop } // end run } // end class
Well, yeah, it triggers a new thread every time, I got that part. It's still a weird thing, because what happens if you just have it all in the actionPerformed() method? Theoretically it should work the same way, unless I'm not getting something.
The user pushes the button (or whatever component has the listener) The actionPerformed() method is called and I/O is done.
If they push it again while the method is still going, what happens? Would it just finish the method first, then run it again? Or would it quit where it is and immediately run the new call? If it immediately quits, then I can see putting it in a thread. But if not, then it seems to only overcomplicate the I/O process.
This post has been edited by Locke: 7 Jul, 2009 - 06:32 PM
If they push it again while the method is still going, what happens? Would it just finish the method first, then run it again? Or would it quit where it is and immediately run the new call? If it immediately quits, then I can see putting it in a thread. But if not, then it seems to only overcomplicate the I/O process.
Yes you will have to wait... there is a single thread that process the events so while you are in the ActionPerformed: - you cannot click somewhere else - you cannot resize the window that is why you do not want user intervention in an ActionPerform
in my second example AskUser runs in its own thread when the actionPerformed wakes it goes back to your main class and execute thisIsAnswer() in its own thread during that time the user can resize the window actually in the example I've post i have a boolean waitingForAnswer that forbids the transaction inside the ActionPerformed() you can be more selective and just forbids the transactions that require user input that way the user can contiunyue to do stuff even if he does not answer right away the question
Yes you will have to wait... there is a single thread that process the events so while you are in the ActionPerformed: - you cannot click somewhere else - you cannot resize the window that is why you do not want user intervention in an ActionPerform
in my second example AskUser runs in its own thread when the actionPerformed wakes it goes back to your main class and execute thisIsAnswer() in its own thread during that time the user can resize the window actually in the example I've post i have a boolean waitingForAnswer that forbids the transaction inside the ActionPerformed() you can be more selective and just forbids the transactions that require user input that way the user can contiunyue to do stuff even if he does not answer right away the question
Ok, I think I get it now. I think I missed the actual point before. I must have missed the OP's _input.readLine() call that must have sparked this discussion.
You're saying put the user I/O in its own thread so that the actionPerformed() method isn't waiting for a response, cutting the user off from interacting with the GUI more, correct? So, when you put it in a separate thread, the actionPerformed() method is free to allow more events to happen.