What I've been up to

These last weeks I was mostly occupied with a somewhat more extensive Java application. At first the goal was to convert an Excel table into another file format.

As time went on though, additional factors turned out to play a role, which would make the whole thing not quite that simple.

Small Overview

I had an example Excel table, that was layed out in the same way as all the other tables that need to be converted. There was also twenty-page specification of the target document format.

The issue with Excel tables: in principle they are not structured. For rows and columns there is no fixed format and users can put data in a cell that - in relation to the target format - doesn’t make a lot of sense. Due to the fact that there’s no unambiguous mapping from the source to the target data, some kind of interactive user interface is a must-have. The user needs to have a way to edit the converted data and, where needed, make manual corrections.

Small Utilities

The CSV parser from http://ostermiller.org/utils/CSV.html was used to read data from the Excel-generated CSV files. Development was done on a Ubuntu Linux machine, but the actual end users would be working in Win2K environment. Naturally this is where Java can play to its cross-platform strength; the JGoodies Look & Feel’s provide for a platform independent, appealing appearance.

Eclipse’s Visual Editor Project was a great help when it came to building the user interface.

Small But Important

During the project a few things popped up that seemed to be quite difficult to solve at first. These were not big, blocking issues, but rather inconveniences for the user of the GUI.

JComboBox is too narrow

A JComboBox, like all other GUI components, is only rendered as wide as the window size and the layout manager allow. No problem per se - but for the fact that the combobox popup is restricted to that same width.

The image on the left demonstrates the issue quite well: this is not a practical way to work. This is a well-known issue by the way. bugs.sun.com has reports going back to late 1998. All the more remarkable that up to this day there is no way to get the desired behavior out of the box.

Multiple workarounds are available though.

Fixed scrollbar position

As soon as the cursor inside of a JTextArea changes its position, the visible area in a JScrollPane gets moved around automtically. Most of the time this is reasonable and desired.

Quick excursion the the previously mentioned import functionality. One particular row in a sample should get copied from the CSV file into the protocol field. The actual text content is almost the same across all samples - paging through them though, it’s important that a particular portion of the protocol is directly visible.

When paging through the samples, the text content of the protocol field (see screenshot) gets replaced every time. This leads to the visible area always scrolling to the very end of the text. It’s relatively easy to change the cursor’s position to somewhere else inside the text area (e.g. the beginning of the document). What I wanted though was to have the scrollbar stay at the same position.

The following code snippet does exactly that:

prevRect = textArea.getVisibleRect();
textArea.setText( someStringHere );

SwingUtilities.invokeLater( new Runnable() {
  public void run() {
    textArea.scrollRectToVisible( prevRect );
  }
});

The important part here is invokeLater. Usually a TextArea updates its model with the new text and then fires an event. That event in turn causes the parent-scrollpane to shift the viewport.

Now, the AWT event handling happens in a separate thread. So if one scrolls somewhere right after setting the text, it’s more than likely that Swing’s internal scroll event gets handled only after that. It happends in a separate thread after all.

Everything is of invokeLater, gets executed inside the AWT event thread – in fact after all other Swing-internal events. Apparently it’s even considered best practive nowadays to push everything into the event thread right at the beginning of the main method.

Contact

Alexander Gitter
contact at agitter net