A more modern style API for the Java Swing UI framework, focused on ease of use.
Let's be honest, coding for Swing is not easy. And JTable is probably the epiphany; you have to understand TableModel, manually add sorting, filtering, the events that trigger updates, etc. What if the Swing API would be revisited and made modern, so that using that JTable becomes simple. What if creating a table with sorting, filtering, automatic updates of cells when values change only took a few lines of code?
var sTable = new STable<City>() //
.columns(City.class, "name", "distance", "roundtrip") //
.data(cities); // cities is a List<City>
Or creating a strongly typed text field the is bound to the property of a Java bean would be as simple as:
var sTextField = STextField.ofBind(city, "name");
Well, you've come to the right place. Take a look at the examples here, and the JavaDoc present in org.tbee.sway, and see if they are easy enough to use. A UI library probably is never truly finished, but Sway is stable and used in production.
// A label can have its text and icon property bound
var sLabel = new Slabel().bindText(city, "name");
// SCheckBox can be bound to a boolean property
var sCheckBox = new SCheckBox("Growing").bind(city, City.GROWING);
// SCheckBox3 can be bound to a Boolean property, supporting 3 states: TRUE, FALSE, NULL
var sCheckBox = new SCheckBox3("Cityrights").bind(city, City.CITYRIGHTS);
// SButtonGroup revolves around the associated value, not the button
var sButtonGroup = new SButtonGroup<Integer>() //
.add(1, new SToggleButton("winner")) //
.add(2, new SToggleButton("2nd")) //
.add(3, new SToggleButton("3rd")) //
.bind(race, "position");
var sPanel = new SFlowPanel(sButtonGroup.getButtons());
// SButtonGroup has some practical convenience methods
var sButtonGroupCities = SButtonGroup.ofRadioButtons(amsterdam, berlin, rome);
var sPanelCities = new SFlowPanel(sButtonGroupCities.getButtons());
// Explicit panels for layouts, with corresponding methods.
var sBorderPanel = new SBorderPanel(new STable()) //
.west(new SomeNavigationMenu()) //
.east(new SomeContextLinks());
// MigLayout is used by Sway anyhow
var migPanel = new MigPanel().fill(); //
migPanel.addLabelAndField(someLabel, someField).growX();
migPanel.wrap();
In order to not have to repeat the same formatting over and over again, Sway has a FormatRegistry.
A simple example:
// Only two methods need to be implemented, the rest are optional
public class LongFormat implements Format<Long> {
@Override
public String toString(Long value) {
return value == null ? "" : value.toString();
}
@Override
public Long toValue(String string) {
return string.isBlank() ? null : Long.parseLong(string);
}
}
// Register the format once to use it in many components
FormatRegistry.register(Long.class, new LongFormat()); // Formats must be stateless and thread safe.
The FormatRegisty is used by all components, STextField, STable, SButtonGroup, ..., so it is only necessary to register a format once. This also is true for domain entities, like for example a "City" or "Employee".
Format also allows to define things like horizontal alignment and icon.
Actions can be registered and will be shown in the (right mouse button) context menu. These can be simple actions, like the default available "copy", "cut" and "paste", but also business model related actions.
ActionRegistry.register(new ShowOnMapForCityTextFields());
SContextMenu.install();
public class ShowOnMapForCityTextFields implements Action {
@Override
public String label() {
return "Show on map";
}
@Override
public boolean isApplicableFor(Component component, Map<String, Object> context) {
return component instanceof STextField sTextField
&& sTextField.getFormat() instanceof CityFormat;
}
@Override
public void apply(Component component, Map<String, Object> context) {
STextField<City> sTextField = (STextField<City>)component;
City city = sTextField.getValue();
... // show city on map
}
}
The components are still the standard Swing components, only with an opinionated API, but they should blend-in nicely in existing applications.
And as long as you stick to Sway's API upgrading should not be too much of a hassle. If you start poking around, you're on your own ;-)
There is no formal support for Sway: this library is an open source hobby project and no claims can be made. Asking for help is always an option. But so is participating, creating pull requests, and other ways of contributing.
- Binding uses Karsten Lentzsch's JGoodies underneath (https://www.jgoodies.com/freeware/libraries/binding/).
- STable's filter header is provided by Coderazzi (https://coderazzi.net/tablefilter/).
- STable's navigation bar is based on CoMedia's implementation (project is no longer available online).
- Mikael Grev's excelent MigLayout is used for several layouts (https://www.miglayout.com/).
And if icons are needed in an application Ikonli is highly suggested! (https://kordamp.org/ikonli/)