Subversion access

Subscribe to Subversion access 3 post(s), 2 voice(s)

 
Avatar chriswil 2 post(s)

Been doing Java development for a while, and I have to admit that I had given up on Swing GUI years ago — until I saw your app. I would love to steal some ideas from you for an app that I’m building. Nothing to do with eBay or auctions, just a simple app with Derby backend. I’m having trouble hooking up to the SVN repository with Eclipse. Is it only accessible through the web interface @ svn.jbidwatcher.com?

Thanks for excellent work. I need to go find the donate page now. Great app.

 
Avatar Morgan Schweers Administrator 1,204 post(s)

Greetings,
Thanks muchly for the kind words… You have to use the svn protocol, not http.

svn://svn.jbidwatcher.com/jbidwatcher/trunk

It’s also available via git on github.

The core problem with Swing is that you have to delegate all actions to a worker thread, and return immediately. Then, when those worker threads want to interact with the UI, they need to (briefly) run in the context of the Swing thread. If you don’t do that, then your UI blocks on your processing, and that leads to a poor user experience. Or, if you try to write to an existing UI element from a different thread, you invariably end up with visual corruption.

My solution to the Swing problem is…unusual. I created pretty much the simplest possible message queuing system, and when you click a menu button, or interact with the UI in some way that the program needs to respond to, it gets put onto a queue for another thread to handle. My queues are named, so there’s code like:

MQFactory.getConcrete("user").enqueue("FAQ");

The UserActions.start() method called
MQFactory.getConcrete("user").registerListener(sInstance = new UserActions());
in order to register to receive queued events, and implements MessageQueue.Listener by providing a UserActions.messageAction(Object deQ) method.

The thing that makes it all work, is a specialized queue I name (for obvious reasons) "Swing". The UIBackbone class does this:

    MQFactory.addQueue("Swing", new SwingMessageQueue());
    MQFactory.getConcrete("Swing").registerListener(this);

The SwingMessageQueue class uses the SwingUtilities.invokeLater method to do the dequeue operation on the Swing thread. Then the UIBackbone code takes the message and translates it into some form of UI interaction with the main frame of the application.

I used the same thing all over the place. There’s a ‘drop’ queue, so when I get a drop message I can just enqueue the data gotten from the drag-and-drop operation, and it’ll get handled out-of-band. There’s a ‘tray’ queue, which handles messages to the system tray. There’s a ‘browse’ queue, which handles launching the browser to a given page. I have a ‘redraw’ queue which handles redrawing individual auction entries. (It uses the SwingUtilities.invokeLater method also, but for a very specialized case.)

There are others, but the idea is pretty consistent. If you need work to be done, and it doesn’t need to be done in-line with the current code, pass it off to a worker thread. If it has to be done in the UI, pass it off to a worker that runs in the Swing thread.

I also have what I call a SuperQueue, which is this amazing (to me) flash of insight that I had, that I could have a task that wakes up every second, and has a list of work to do at particular times. When the time arrives to do the work, all it does is move the payload to a given queue. This way I can say things like:

SuperQueue.getInstance().preQueue("http://www.jbidwatcher.com", "browse", System.currentTimeMillis() + (Constants.ONE_MINUTE / 4);
and in 15 seconds that’ll queue the ‘browse’ thread to tell the browser to go to the JBidwatcher home page. This is especially useful for sniping, obviously. :)

I probably abuse it a little bit, but it’s an amazingly useful set of tricks. It’s probably not ‘new’, but when I first built it back in 2000, I didn’t know of anybody else who was using this kind of a message queue to distribute work to their various threads.

Useful code includes:

You don’t need to go this complex. Most applications can resolve what they need to do with judicious use of threads and SwingUtilities.invokeLater with anonymous runnable classes.

Hope this info helps!

— Morgan Schweers, Cyber*FOX*!

 
Avatar chriswil 2 post(s)

Doh! I should have caught that svn: protocol stuff. Brain dead on a Sunday morning.

I like your threading strategy. I see some good design patterns in use there.

Thanks again.