I have written a GUI for operating a card reader - mainly consisting of an ADD button that brings up a FileChooser
dialog and queues the chosen File
onto a CardHopper, which is displayed visually as a JList
.
Now I want for the CPU (another JFrame
, on another thread) to be able to make requests of the card reader; e.g. read a card and send it to me. Before the card reader had a GUI, it was just a model that ran on the same thread as the CPU, so I could just call its readCard()
method. Now that it's on a separate thread, it seems like the right way to communicate is with message-pass开发者_如何学编程ing.
I was about to implement something using a PriorityBlockingQueue
, whereby the CPU would put
a read-card command on the queue and the CardReader would take
and execute the command, until I realized that the CardReader thread would normally be blocked somewhere within its NetBeans-supplied Swing code, waiting for a GUI event and blind to the arrival of anything on my event queue. Moreover, this "back end" request would alter the data model - so even if I could somehow execute some code in the model, would it be kosher to "fire" notifications to the GUI's ListDataListeners
while the GUI is waiting for GUI events?
I hope this isn't too cryptic - I'm still trying to get my arms around the mechanics of GUIs and threads.
Would it be kosher to "fire" notifications to the GUI's ListDataListeners while the GUI is waiting for GUI events?
Absolutely not.
What you want to do is perform all tasks that directly manipulate your UI's models (or call UI functions) on the Swing event thread.
Essentially, when you're ready to post an event that will perform some UI task, do it like:
SwingUtilities.invokeLater(new Runnable() {
public void run() {
...
}
}
You can fire all your listeners, and do whatever you want to your ListModel (or your other UI models) there since it will only get run in the Swing thread.
Otherwise, you risk Swing trying to read you data while it is painting and you are updating your data. You'll start getting NullPointerException, ArrayIndexOutOfBoundExceptions, ConcurrentModifictionException, etc.
Ideally, you would perform all of your background work in a separate thread (or under SwingWorker), and then when everything is ready, push an update via invokeLater.
精彩评论