Skip to main content
  1. Softwares/

OBJ2GUI3 (preview)

·444 words·3 mins
Table of Contents

About
#

OBJ2GUI3 is the successor of OBJ2GUI2 : a Java Swing library for automatic GUI generation from annotated objects, redesigned from scratch with a more modern approach and built-in memory leak prevention.

Select one object and you get a classic form. Select several and you get multi-object editing : fields with differing values are highlighted in orange, and typing a value applies it to the whole selection.

Multi-object editing : 3 persons selected, differing fields highlighted
Editing 3 objects at once — orange fields have different values across the selection

Preview — the library is in active development and the API may still change. It is not yet published on Maven Central.

What changes from OBJ2GUI2
#

OBJ2GUI2OBJ2GUI3
Annotationson fieldson getters — computed/derived values can be displayed too
Property namesstrings ("name")type-safe method references (Person::getName)
Listenersstrong referencesweak references — discarded forms cannot leak memory
Undo/Redononebuilt-in, including multi-object edits as compound commands
Mixed selectionsingle typeheterogeneous — objects grouped by type automatically
Look & FeelSwing defaultFlatLaf light/dark + MigLayout

How it works
#

Your DTO implements Observable and annotates its getters — which means a form can also display computed values, something field annotations could never do:

public class Person implements Observable {
    public final ObservableSupport observable = new ObservableSupport(this);

    @O2G3Property(label = "Name", orderDisplay = 10)
    public String getName() { return name; }

    public void setName(String name) {
        String old = this.name;
        this.name = name;
        firePropertyChange(old, name);   // setter name determined automatically
    }

    // Read-only computed property
    @O2G3Property(label = "Summary", orderDisplay = 30, readOnly = true)
    public String getSummary() { return name + " (" + age + ")"; }

    // Nested object gets its own sub-form
    @O2G3NestedObject
    public Address getAddress() { return address; }

    // List property with its own add/remove editor
    @O2G3ListProperty(label = "Dogs", orderDisplay = 100, itemType = Dog.class)
    public List<Dog> getAnimaux() { return animaux; }
}

Then a fluent builder assembles the form — with undo/redo and ComboBox bindings fed from your domain objects:

UndoRedoManager undoManager = new UndoRedoManager(50);

Binding deptBinding = new Binding(departments, Person.class,
        PropertyNameExtractor.getPropertyName(Person::getDepartment));

JPanel form = new MultiObjectFormBuilder(undoManager)
        .withObjects(selectedPersons)          // one or many
        .withBindings(List.of(deptBinding))
        .build();

Widgets are auto-detected from the property type (TextField, Spinner, Slider, CheckBox, ComboBox, TextArea…), and programmatic changes to the model are reflected back into the form thanks to the observable DTOs — through weak listeners, so a closed form can never keep your objects alive.

Screenshots
#

Single selection : a classic generated form
Single selection — a classic generated form

Dark mode with FlatLaf
FlatLaf dark mode

Roadmap
#

  • Externalized labels (i18n) with convention-over-configuration and fallback to annotation labels
  • Plugin system for custom types
  • Dark-mode-aware difference highlighting colors

GitHub link#

Source code is available in GitHub


comments powered by Disqus