Swing’s JComboBox
The JComboBox in Java Swing can be used in two environments. The first is as normal component in a container and second as editor in a table, tree or list. In the first case every selection made in the list is propagated to the combo-box whereas in the second case it is only propagated when the popup is closed by pressing the enter key. Often the second behavior is better, especially when it comes to triggering a background task when the user finished the selection. There is already a bug in the Sun Bug database which discusses the correct behavior.
For uneditable combo-boxes it is easy to implement by simply overriding firePopupMenuCanceled(), firePopupMenuWillBecomeInvisible(), firePopupMenuWillBecomeInvisible() and fireActionPerformed(). Problems are starting when the combo-box is editable. In this case the editor didn’t update when the selection is finished. In the methods fire*Canceled() and fire*WillBecomeInvisibel() the property „JComboBox.isTableCellEditor“ is set to Boolean.FALSE, in fire*WillBecomeVisible() this property is set to Boolean.TRUE to activate/deactivate the behavior when the popup is shown/hidden before delegating to the super implementation. In fireActionPerformed() the popup needs to be hidden after before delegating to the super implementation.
Now in an editable combo box when the popup is going to be hidden the method actionPerformed(ActionEvent) is invoked. I finally found this by searching some hours through the code. To solve the update problem I need access to the popup. But the BasicComboBoxUI doesn’t provide any method therefore.
public void actionPerformed(ActionEvent evt) {
ui = (BasicComboBoxUI) getUI();
try {
Field popupField = BasicComboBoxUI.class.getDeclaredField("popup");
popupField.setAccessible(true);
ComboPopup popup = (ComboPopup) popupField.get(ui);
int selectedIndex = popup.getList().getSelectedIndex();
setSelectedIndex(selectedIndex);
} catch (NoSuchFieldException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} finally {
super.actionPerformed(evt);
}
}
This snippet accesses the protected field, retrieves the selected index from the list in the popup and updates the combo box with the selected index which also updates the editor and model.
This hacky solution makes it possible to solve the problem but is completely against any OO principle. Going further one can inject different popups and customize the combo box but it is still against information hiding and encapsulation.
Isn’t there a better solution???
Diätenerhöhung
Eine Erhöhung von 15 Prozent über 3 Jahre sind ungefähr 5 Prozent im Jahr. Wie hat Trichet nicht zum Anfang dieses Jahres gewarnt, dass eine erhöhte Lohnsteigerung in Deutschland für Europa nur zu einer erhöhten Inflation führen wird. Das würde die Inflationsspirale nur immer mehr antreiben. Durch die höheren Löhne die Produktionskosten ebenfalls wieder steigen, was zu einer Preissteigerung führt. Diese führt dann irgendwann wieder zu einer Lohnsteigerung. Jedenfalls haben unsere regierenden Politiker nichts weiter im Sinn, als mit gutem Beispiel voranzugehen und sich die Diäten um 5 Prozent zu erhöhen. Anstatt vielleicht aufgrund der aktuellen Situation eine geringere Erhöhung in Kauf zu nehmen. Vorerst könnten Diäten an einen Durchschnittswert gekoppelt sein, z.B. an die durchschnittlichen Löhne und Gehälter in Deutschland? Das lange Ziel sollte aber sein Deutschland zu einem unternehmerisch denkenden Staat umzubauen, bei dem es Lohn oder Gehalt auch für eine erfolgreiche Leistung gibt.
Background execution of long running operations
After showing some problems with the synchronous solutions like Foxtrot or Spin. Now I want to talk about Swing Application Framework’s TaskService or a small own solution.
The Swing Application Framework uses annotated methods which can be executed as during the actionPerformed() method of an Action. The method can return a task to indicate that it needs to be executed in the background. This Task object is handed over to the TaskService which executes it in a background thread, like a SwingWorker. The Task object might have a blocking scope that defines how much of the user interface is blocked during execution. This is quite easy and works very well.
My problem is the Task class which not only contains information about how to block, but also the responsibility to create the blocker and a reference to the task service. If there are multiple tasks it might be possible that two blockers show a dialog
. I would like to have a Task which is small and easy, like a command object from the command pattern. The command or task should then be handed over to the so called TaskService and this one should execute it.
First the Task needs to be simplified. Therefore the responsibility of creating and maintaining the InputBlocker moves over to the TaskService. The service has a single input blocker which is used in the complete application. So it has a unique interface and can also show a list of running tasks like the ProgressView of Eclipse. The service also should implement the Executor interface which makes it possible that even Runnable objects can be executed over this service. The service distinguishes between a Runnable object and a Task and can use a default blocking behavior like blocking the complete application. If the TaskService extends ThreadPoolExecutor it is easy to implement input blocking by blocking either in execute() or beforeExecute() and unblocking in afterExecute().
The Task class is then a simple extension of SwingWorker with some visual attributes like title and description, running time. An important BlockingScope that defines how much is blocked and an optional source from which the input blocker is able to block the user interface.
The image shows possible classes for the simplified service. I renamed the Task to SwingWorkerExt because it is a simple extension of SwingWorker. The enumeration BlockingScope and the interface InputBlocker stays as in the SwingApplicationFramework. But instead of having an association between InputBlocker and SwingWorkerExt, the input blocker only works together with the executor. In this case the SwingThreadPoolExecutor is the service used to execute background operations. introducing events when a command is added, removed, executed or rejected also helps the application to better react in extrem conditions.
Provider-Wechsel
Mit dem letzten Update von WordPress funktioniert auf meinem alten Provider das Schreiben von Artikeln nicht mehr. Selbst wenn ich das Update zurückrolle können keine Artikel mehr erstellt werden. Deswegen habe ich diesen Blog erstellt und werde mit der Zeit alle alten Artikel in diesen übernehmen. Bis auf weiteres wird hier weitergebloggt.
Freezing the user interface
Looking around for a good framework that encapsulates the user interface freeze problem in Swing I found Spin, Foxtrot and the Swing Application Framework’s Task framework. From executing the tests it seems that Spin and Foxtrot both have a problem on the Metal Look&Feel. The pressed button looks pressed as long as the mouse stays over it or doesn’t hit the boundaries and initiate a mouse entered or exited event. This mainly happens because the method blocks inside the actionPerformed until the background thread is finished. These frameworks reroute the Event-Dispatch-Thread (EDT) to a different event queue. The bug somehow doesn’t happen with the Windows Look&Feel.
With the Swing Application Framework’s Task framework this doesn’t happen because the task will be sent to an executor service which executes it and the method returns immediately. There is no EDT rerouting or blocking involved.


