General

  • Preferences are stored in registry on windows, and elsewhere in linux. See this.  

Swing

Text fields

  • After a user edits a text field, the new value should be committed in response to either the user pressing ENTER or switching focus to another component. That is, in response to either:
    • actionPerformed
    • focusLost -- but note for this one that when processing the FocusEvent evt you should only process the commit if !evt.isTemporary(). A temporary event is caused by the mouse being moved on top of another panel, e.g. the 3D view, and you don't want to commit the value just because of that.
  • If the value entered is numeric and you parse it using e.g. Double.valueOf(COMPONENT.getText()), you should always surround withtry,catch to catch a parsing exception (and if one is caught you replace the text of the component with the previous value from the underlying model).
  • Another catch regarding focusLost events: If you have a panel with a table and some text fields (e.g. look at the Scale Factors tab of the scale tool), and you want a value entered into the text field to be applied to the currently selected row(s) of the table, you have to be careful. Suppose you enter some value into the text field and then (without yet pressing Enter) you select another row of the table. Then a focus lost event is processed for the text field but you can't apply the changes to the table's getSelectedRows() because they've already been updated to the new selection. i.e. if you do this wrong you will see the values applied to the new selection rather than the previously selected row(s). So what you need to do (see ScaleFactorsPanel.java for example) is to store a local copy of the currently selected rows which is only updated in response to a selection changed event. It turns out that the sequence of events in the scenario described would be
    • table's internal selected rows variable is updated to new selection
    • focus lost processed for text field
    • callback is called for changed selection
  • so as you can see it is not safe to query the table's internal current selection during the focus lost event but it is okay to use your cached value which is only updated in the third step.
  • Related to this, in my test MeasurementSet GUI, I couldn't set the extra stuff to setFocusable(false) because then if you've edited the text field and you click on "ADD" or "REMOVE" MEASUREMENT button then the text field won't lose focus until after the add/remove action has taken place, by which point it is not safe to try to rename anything in the measurement set...

Panels

  • To use a custom JPanel as a component in another panel, go to Code/Custom Creation Code and enter new IKMarkerTaskPanel(model); or whatever

3D View

  • ViewDB.getInstance().repaintAll() schedules a repaint for later, while ViewDB.getInstance().renderAll() renders immediately. The former tends to not refresh the view often enough (e.g. during the dragging of a muscle point, lots of other events saturate the queue so repaint barely happens). The latter seems better in those cases.

Miscellaneous

  • Rerouting System.out and System.err to a logger -- see this