Files
playbook/skills/thirdparty/ui-ux-pro-max/data/stacks/javafx.csv
T

33 KiB

1NoCategoryGuidelineDescriptionDoDon'tCode GoodCode BadSeverityDocs URLApplies ToStatusVerified At
21ApplicationStart UI from Application subclassJavaFX apps should bootstrap the primary Stage through Application.start()Extend Application and configure Scene in start()Create UI from a random main method without launching JavaFXpublic class App extends Application { public void start(Stage stage) { stage.setScene(new Scene(root)); stage.show(); } }new Stage().show()Highhttps://openjfx.io/javadoc/26/javafx.graphics/javafx/application/Application.htmljavafx 26active2026-08-13
32ThreadingKeep work off the FX Application ThreadLong-running work blocks rendering and input when executed on the UI threadUse Task or Service for background workRun network database or file work in button handlersTask<List<Item>> task = new Task<>() { protected List<Item> call() { return repo.load(); } }; new Thread(task).start();loadLargeFile(); table.setItems(items);Highhttps://openjfx.io/javadoc/26/javafx.graphics/javafx/concurrent/Task.htmljavafx 26active2026-08-13
43ThreadingUpdate UI only on FX threadScene graph changes must happen on the JavaFX Application ThreadUse bindings task handlers or Platform.runLater for UI changesMutate controls directly from background threadstask.setOnSucceeded(e -> table.setItems(FXCollections.observableArrayList(task.getValue())));new Thread(() -> label.setText("Done")).start()Highhttps://openjfx.io/javadoc/26/javafx.graphics/javafx/application/Platform.htmljavafx 26active2026-08-13
54ThreadingBind progress to background tasksTask exposes progress and message properties for responsive feedbackBind ProgressBar and Label to task propertiesPoll progress manually or leave users without feedbackprogress.progressProperty().bind(task.progressProperty()); status.textProperty().bind(task.messageProperty());while(running) progress.setProgress(x);Mediumhttps://openjfx.io/javadoc/26/javafx.graphics/javafx/concurrent/Task.htmljavafx 26active2026-08-13
65FXMLUse FXML for stable declarative layoutsFXML keeps view structure readable for screens with many controlsPlace layout in FXML and behavior in controllerBuild large screens entirely in one Java method<VBox spacing="12" xmlns:fx="http://javafx.com/fxml" fx:controller="app.MainController">VBox root = new VBox(); root.getChildren().add(... 200 lines ...);Mediumhttps://openjfx.io/javadoc/26/javafx.fxml/javafx/fxml/FXMLLoader.htmljavafx 26active2026-08-13
76FXMLKeep controllers focused on view behaviorControllers should coordinate controls and delegate business logic to servicesInject services or call application services from controllerPut database queries and domain rules directly in controllerpublic void save() { customerService.save(form.toCommand()); }public void save() { DriverManager.getConnection(...); }Highhttps://openjfx.io/javadoc/26/javafx.fxml/javafx/fxml/FXML.htmljavafx 26active2026-08-13
87FXMLUse fx:id for injected controlsFXML controls need stable fx:id values that match controller fieldsAnnotate fields with @FXML and keep ids descriptiveLook up controls by CSS selector for normal wiring@FXML private TableView<Customer> customerTable;root.lookup("#customerTable")Mediumhttps://openjfx.io/javadoc/26/javafx.fxml/javafx/fxml/FXML.htmljavafx 26active2026-08-13
98FXMLFail fast when loading FXMLFXML load errors should surface during screen creation with clear contextLoad resources with getResource and handle IOException explicitlySwallow loader errors and show a blank sceneURL view = getClass().getResource(\/views/main.fxml\"); Parent root = FXMLLoader.load(view);"try { FXMLLoader.load(url); } catch(Exception ignored) {}Highhttps://openjfx.io/javadoc/26/javafx.fxml/javafx/fxml/FXMLLoader.htmljavafx 26active2026-08-13
109CSSStyle with style classesJavaFX CSS works best through reusable styleClass namesAdd semantic style classes and define them in CSSSet long inline style strings throughout codebutton.getStyleClass().add(\primary-action\");".setStyle(\-fx-background-color: #2563eb; -fx-padding: 12; ...\")"Mediumhttps://openjfx.io/javadoc/26/javafx.graphics/javafx/scene/doc-files/cssref.htmljavafx 26active2026-08-13
1110CSSUse design tokens through looked-up colorsLooked-up colors keep palettes consistent across controlsDefine named colors on root and reuse them in CSSRepeat hex values in every selector.root { -brand-primary: #2563eb; } .button.primary { -fx-background-color: -brand-primary; }.save { -fx-background-color: #2563eb; } .link { -fx-text-fill: #2563eb; }Mediumhttps://openjfx.io/javadoc/26/javafx.graphics/javafx/scene/doc-files/cssref.htmljavafx 26active2026-08-13
1211CSSAvoid overusing inline effectsExpensive CSS effects and shadows can hurt desktop UI responsivenessUse subtle shadows only on important elevated surfacesApply blur drop shadow and glow to every node.dialog-card { -fx-effect: dropshadow(gaussian, rgba(0,0,0,.18), 16, 0, 0, 4); }.table-row-cell { -fx-effect: dropshadow(gaussian, black, 20, .5, 0, 0); }Mediumhttps://openjfx.io/javadoc/26/javafx.graphics/javafx/scene/effect/package-summary.htmljavafx 26active2026-08-13
1312LayoutChoose layout panes by responsibilityEach pane solves a different layout problem and should be selected intentionallyUse BorderPane for app shell GridPane for forms VBox/HBox for simple stacksUse absolute positioning for resizable app screensBorderPane shell = new BorderPane(); shell.setTop(toolbar); shell.setCenter(content);Pane root = new Pane(); button.setLayoutX(742);Highhttps://openjfx.io/javadoc/26/javafx.graphics/javafx/scene/layout/package-summary.htmljavafx 26active2026-08-13
1413LayoutPrefer constraints over fixed coordinatesResponsive JavaFX layouts depend on constraints and grow prioritiesUse hgrow vgrow column constraints and alignmentHard-code pixel positions and sizesGridPane.setHgrow(nameField, Priority.ALWAYS); column.setPercentWidth(50);field.setPrefWidth(328); field.setLayoutX(120);Highhttps://openjfx.io/javadoc/26/javafx.graphics/javafx/scene/layout/GridPane.htmljavafx 26active2026-08-13
1514LayoutSet sensible min pref and max sizesControls should resize predictably across windows and DPI settingsUse Region.USE_COMPUTED_SIZE and max widths intentionallyLock every control to fixed width and heightbutton.setMaxWidth(Double.MAX_VALUE); VBox.setVgrow(table, Priority.ALWAYS);button.setMinSize(96, 32); button.setMaxSize(96, 32);Mediumhttps://openjfx.io/javadoc/26/javafx.graphics/javafx/scene/layout/Region.htmljavafx 26active2026-08-13
1615LayoutUse spacing and padding consistentlyDesktop UI needs scan-friendly rhythm and clear groupingSet spacing padding and Insets through shared constants or CSSUse inconsistent ad hoc gaps between controlsform.setHgap(12); form.setVgap(10); form.setPadding(new Insets(16));box.setSpacing(3); other.setSpacing(17);Lowhttps://openjfx.io/javadoc/26/javafx.graphics/javafx/geometry/Insets.htmljavafx 26active2026-08-13
1716ControlsUse ObservableList for list controlsTableView ListView and ComboBox update automatically from observable collectionsBack controls with FXCollections.observableArrayList()Mutate plain lists and manually refresh controlsObservableList<Customer> rows = FXCollections.observableArrayList(); table.setItems(rows);List<Customer> rows = new ArrayList<>(); table.setItems((ObservableList) rows);Highhttps://openjfx.io/javadoc/26/javafx.base/javafx/collections/ObservableList.htmljavafx 26active2026-08-13
1817ControlsConfigure TableView cell value factories with propertiesTable columns should observe stable JavaFX properties for updatesExpose StringProperty ObjectProperty or use ReadOnlyObjectWrapperReturn transient strings without observable supportnameCol.setCellValueFactory(data -> data.getValue().nameProperty());nameCol.setCellValueFactory(data -> new SimpleStringProperty(data.getValue().toString()));Mediumhttps://openjfx.io/javadoc/26/javafx.controls/javafx/scene/control/TableColumn.htmljavafx 26active2026-08-13
1918ControlsUse cell factories for custom renderingCustom table or list visuals belong in reusable cell factoriesOverride updateItem and handle empty statePlace complex Nodes directly in model objectscol.setCellFactory(c -> new TableCell<>() { protected void updateItem(Status s, boolean empty) { super.updateItem(s, empty); setText(empty ? null : s.label()); } });row.setBadge(new Label("Active"));Mediumhttps://openjfx.io/javadoc/26/javafx.controls/javafx/scene/control/Cell.htmljavafx 26active2026-08-13
2019ControlsVirtualized controls are for large dataTableView ListView TreeView virtualize cells and outperform manual node listsUse TableView or ListView for hundreds of rowsCreate hundreds of HBoxes inside a VBoxListView<Item> list = new ListView<>(items);items.forEach(i -> vbox.getChildren().add(new ItemRow(i)));Highhttps://openjfx.io/javadoc/26/javafx.controls/javafx/scene/control/ListView.htmljavafx 26active2026-08-13
2120ControlsHandle empty states explicitlyEmpty tables and lists need visible guidance or next actionsSet placeholder nodes for empty data viewsLeave blank white areas that look brokentable.setPlaceholder(new Label(\No customers match this filter\"));"table.setPlaceholder(null);Lowhttps://openjfx.io/javadoc/26/javafx.controls/javafx/scene/control/TableView.htmljavafx 26active2026-08-13
2221BindingUse property binding for derived UI stateJavaFX binding reduces imperative synchronization bugsBind disabled visible text and progress properties to source stateManually update every dependent control in each event handlersaveButton.disableProperty().bind(form.validProperty().not());if(!valid) saveButton.setDisable(true);Highhttps://openjfx.io/javadoc/26/javafx.base/javafx/beans/binding/Bindings.htmljavafx 26active2026-08-13
2322BindingUnbind before manual updatesBound properties cannot be set directly without errorsCall unbind when switching from bound to manual stateSet a bound property directlylabel.textProperty().unbind(); label.setText(\Ready\");"label.textProperty().bind(task.messageProperty()); label.setText(\"Ready\");Mediumhttps://openjfx.io/javadoc/26/javafx.base/javafx/beans/property/Property.htmljavafx 26active2026-08-13
2423BindingUse listeners sparinglyBindings express simple relationships more clearly than listenersUse listeners for side effects and bindings for valuesCreate listener chains for simple computed texttotalLabel.textProperty().bind(Bindings.format("Total: %d", total));count.addListener((o, a, b) -> totalLabel.setText("Total: " + b));Lowhttps://openjfx.io/javadoc/26/javafx.base/javafx/beans/value/ObservableValue.htmljavafx 26active2026-08-13
2524EventsUse action handlers for commandsButtons and menu items should route to named command methodsUse setOnAction or @FXML handler methods with clear namesPut large lambdas inline for complex operations@FXML private void handleSave(ActionEvent event) { saveCustomer(); }saveButton.setOnAction(e -> { validate(); transform(); query(); save(); refresh(); });Mediumhttps://openjfx.io/javadoc/26/javafx.base/javafx/event/ActionEvent.htmljavafx 26active2026-08-13
2625EventsUse event filters for global shortcutsFilters can intercept keyboard events before child controls consume themRegister accelerators or filters at Scene levelAdd duplicate key handlers to every controlscene.getAccelerators().put(new KeyCodeCombination(KeyCode.S, SHORTCUT_DOWN), this::save);nameField.setOnKeyPressed(...); table.setOnKeyPressed(...);Mediumhttps://openjfx.io/javadoc/26/javafx.graphics/javafx/scene/Scene.htmljavafx 26active2026-08-13
2726AccessibilityConnect labels to inputsAccessible desktop forms need labels associated with controlsUse Label.setLabelFor and clear prompt textUse placeholder-only labelsnameLabel.setLabelFor(nameField); nameField.setPromptText(\Jane Doe\");"nameField.setPromptText(\"Name\");Highhttps://openjfx.io/javadoc/26/javafx.controls/javafx/scene/control/Label.htmljavafx 26active2026-08-13
2827AccessibilityExpose accessible text for icon buttonsIcon-only controls need names for screen readers and tooltipsSet accessibleText and Tooltip on icon buttonsUse unlabeled graphic-only buttonsbutton.setAccessibleText("Refresh"); button.setTooltip(new Tooltip("Refresh"));new Button("", refreshIcon)Highhttps://openjfx.io/javadoc/26/javafx.graphics/javafx/scene/AccessibleRole.htmljavafx 26active2026-08-13
2928AccessibilityKeep keyboard focus visibleDesktop users rely on focus traversal and visible focus indicatorsPreserve focus rings and tab orderRemove outlines without alternative focus state.button:focused { -fx-border-color: -brand-focus; -fx-border-width: 2; }.button:focused { -fx-background-insets: 0; }Highhttps://openjfx.io/javadoc/26/javafx.graphics/javafx/scene/Node.htmljavafx 26active2026-08-13
3029AccessibilityUse mnemonics for menu and form workflowsMnemonics make desktop workflows faster and more accessibleEnable mnemonicParsing and choose unique mnemonic lettersIgnore keyboard alternatives for frequent actionssaveButton.setMnemonicParsing(true); saveButton.setText("_Save");saveButton.setText("Save");Lowhttps://openjfx.io/javadoc/26/javafx.controls/javafx/scene/control/Labeled.htmljavafx 26active2026-08-13
3130ValidationShow validation near the fieldUsers should not hunt for form errors in desktop dialogsBind error labels or pseudo classes next to invalid controlsShow only a generic alert after submitfield.pseudoClassStateChanged(PseudoClass.getPseudoClass("invalid"), !valid);new Alert(ERROR, "Invalid input").show();Mediumhttps://openjfx.io/javadoc/26/javafx.graphics/javafx/css/PseudoClass.htmljavafx 26active2026-08-13
3231ValidationUse TextFormatter for constrained inputTextFormatter prevents invalid edits before they enter the modelAttach TextFormatter for numeric dates and masksParse and reject invalid text only after submitamountField.setTextFormatter(new TextFormatter<>(new IntegerStringConverter(), 0, c -> c.getControlNewText().matches("\\d*") ? c : null));Integer.parseInt(amountField.getText());Mediumhttps://openjfx.io/javadoc/26/javafx.controls/javafx/scene/control/TextFormatter.htmljavafx 26active2026-08-13
3332DialogsUse modal ownership for dialogsDialogs should block only the relevant window and return structured resultsSet owner modality and use showAndWaitOpen unmanaged windows for confirmationsdialog.initOwner(stage); dialog.initModality(Modality.WINDOW_MODAL); Optional<ButtonType> result = dialog.showAndWait();new Stage().show();Mediumhttps://openjfx.io/javadoc/26/javafx.graphics/javafx/stage/Modality.htmljavafx 26active2026-08-13
3433DialogsPrefer custom DialogPane over ad hoc stagesDialog gives consistent buttons focus and result handlingUse Dialog<T> for forms confirmations and wizardsBuild every modal as a new Stage manuallyDialog<Customer> dialog = new Dialog<>(); dialog.getDialogPane().getButtonTypes().addAll(OK, CANCEL);Stage modal = new Stage(); modal.setScene(new Scene(new VBox()));Lowhttps://openjfx.io/javadoc/26/javafx.controls/javafx/scene/control/Dialog.htmljavafx 26active2026-08-13
3534ImagesLoad images as resourcesPackaged apps need resources resolved from the classpath or module pathUse getResourceAsStream for bundled assetsUse absolute local file paths in production UInew Image(getClass().getResourceAsStream("/images/logo.png"));new Image("file:/Users/me/Desktop/logo.png")Highhttps://openjfx.io/javadoc/26/javafx.graphics/javafx/scene/image/Image.htmljavafx 26active2026-08-13
3635ImagesUse background loading for large imagesLarge image decoding can pause UI startupUse Image(url true) or a background Task for heavy assetsLoad many full-size images synchronously during startupImage preview = new Image(url, true);gallery.add(new Image(url));Mediumhttps://openjfx.io/javadoc/26/javafx.graphics/javafx/scene/image/Image.htmljavafx 26active2026-08-13
3736AnimationKeep animations purposeful and shortDesktop UI animations should clarify state changes without delaying workUse 150-250ms transitions for reveal hover and selectionAnimate every layout change with long timelinesFadeTransition ft = new FadeTransition(Duration.millis(180), pane); ft.setToValue(1);new Timeline(new KeyFrame(Duration.seconds(2), ...)).play();Lowhttps://openjfx.io/javadoc/26/javafx.graphics/javafx/animation/package-summary.htmljavafx 26active2026-08-13
3837AnimationRespect reduced-motion contexts where possibleSome users experience motion sensitivity in desktop appsProvide a setting to disable decorative animationsMake animation required for comprehensionif (settings.reducedMotion()) pane.setOpacity(1); else fade.play();alwaysSpin.play();Mediumhttps://openjfx.io/javadoc/26/javafx.graphics/javafx/animation/Animation.htmljavafx 26active2026-08-13
3938PerformanceAvoid recreating scenes for small state changesReplacing whole scenes loses state and can flickerSwap center content or update view modelsRebuild the entire Stage for every navigation clickshell.setCenter(customerView);stage.setScene(new Scene(loadMainAgain()));Mediumhttps://openjfx.io/javadoc/26/javafx.graphics/javafx/scene/Scene.htmljavafx 26active2026-08-13
4039PerformanceReuse loaded views when appropriateFXML loading and CSS application are not freeCache stable views or controllers for frequent navigationReload heavyweight screens repeatedly without needNode settings = viewCache.computeIfAbsent("settings", this::loadSettings);button.setOnAction(e -> shell.setCenter(loadFxml("settings.fxml")));Lowhttps://openjfx.io/javadoc/26/javafx.fxml/javafx/fxml/FXMLLoader.htmljavafx 26active2026-08-13
4140PerformanceBatch observable list changesMany single-item updates can cause repeated layout and sort workUse setAll or addAll for bulk replacementLoop add items one by one to visible listsitems.setAll(repository.findAll());for(Item item : loaded) items.add(item);Mediumhttps://openjfx.io/javadoc/26/javafx.base/javafx/collections/ObservableList.htmljavafx 26active2026-08-13
4241ArchitectureUse view models for complex screensView models keep controller state testable and separate from controlsExpose JavaFX properties from a screen modelStore all state only inside controlscustomerNameField.textProperty().bindBidirectional(viewModel.nameProperty());String name = customerNameField.getText(); // everywhereMediumhttps://openjfx.io/javadoc/26/javafx.base/javafx/beans/property/package-summary.htmljavafx 26active2026-08-13
4342ArchitectureSeparate navigation from feature controllersFeature controllers should not know how every screen is launchedUse a navigator or application shell serviceCall FXMLLoader for unrelated screens from each controllernavigator.showCustomers();FXMLLoader.load(getClass().getResource(\"/views/admin.fxml\"));Mediumhttps://openjfx.io/javadoc/26/javafx.fxml/javafx/fxml/FXMLLoader.htmljavafx 26active2026-08-13
4443ModulesDeclare required JavaFX modulesModular JavaFX apps must require the modules they useAdd javafx.controls javafx.fxml and opens controller packagesDepend on classpath accidents onlymodule app { requires javafx.controls; requires javafx.fxml; opens app.ui to javafx.fxml; }module app { requires javafx.controls; }Highhttps://openjfx.io/openjfx-docs/#modularjavafx 26active2026-08-13
4544PackagingUse jlink or jpackage for desktop deliveryJavaFX apps should ship with the runtime they needPackage a runtime image or native installerAsk end users to install matching Java and JavaFX manuallyjpackage --name MyApp --module app/app.Main --runtime-image build/imagejava -jar app.jarMediumhttps://openjfx.io/openjfx-docs/#modularjavafx 26active2026-08-13
4645TestingUse TestFX for interaction testsUI flows need automated coverage beyond controller unit testsWrite TestFX tests for key forms dialogs and navigationOnly manually click through releasesclickOn("#nameField").write("Alice"); clickOn("Save"); verifyThat("Saved", isVisible());// manual QA onlyMediumhttps://github.com/TestFX/TestFXjavafx 26active2026-08-13
4746ThemeUse AtlantaFX as the enterprise theme baselineAtlantaFX provides modern JavaFX themes while preserving standard controlsUse AtlantaFX user-agent stylesheet plus a small app CSS layerRewrite every standard control style from scratchApplication.setUserAgentStylesheet(new PrimerLight().getUserAgentStylesheet());scene.getStylesheets().add("/css/huge-custom-theme.css");Highhttps://mkpaz.github.io/atlantafx/getting-started/javafx 26active2026-08-13
4847ThemePrefer Primer for enterprise applicationsPrimerLight and PrimerDark are neutral enough for dense business workflowsUse PrimerLight as default and PrimerDark for dark modeUse Dracula or Cupertino as the default enterprise themeApplication.setUserAgentStylesheet(new PrimerLight().getUserAgentStylesheet());Application.setUserAgentStylesheet(new Dracula().getUserAgentStylesheet());Mediumhttps://mkpaz.github.io/atlantafx/themes/javafx 26active2026-08-13
4948ThemeLayer brand CSS after AtlantaFXApplication CSS should customize brand tokens and business states after the base themeAdd app.css to the Scene after setting AtlantaFXEdit AtlantaFX source CSS directlyscene.getStylesheets().add(getClass().getResource("/css/app.css").toExternalForm());modify atlantafx-base CSS filesHighhttps://mkpaz.github.io/atlantafx/theming/javafx 26active2026-08-13
5049ThemeUse looked-up colors as enterprise tokensJavaFX looked-up colors keep brand and semantic colors reusable across controlsDefine app-primary app-success app-warning app-danger on rootRepeat hex values in every selector.root { -app-primary: #2563eb; -app-danger: #dc2626; }.save { -fx-background-color: #2563eb; } .link { -fx-text-fill: #2563eb; }Highhttps://openjfx.io/javadoc/26/javafx.graphics/javafx/scene/doc-files/cssref.htmljavafx 26active2026-08-13
5150ThemeKeep theme switching centralizedDark mode switching should not be scattered across controllersUse a ThemeService that sets user-agent stylesheet and app CSS variantsLet each controller decide its own themethemeService.apply(ThemeMode.DARK);if(dark) button.setStyle(...);Mediumhttps://mkpaz.github.io/atlantafx/javafx 26active2026-08-13
5251ThemeValidate contrast for business status colorsEnterprise screens use status colors heavily and need readable contrastCheck text on success warning danger and selected row backgroundsAssume brand colors are accessible.status-danger { -fx-text-fill: -app-danger; }red text on dark red backgroundHighhttps://www.w3.org/WAI/WCAG22/Understanding/contrast-minimum.htmljavafx 26active2026-08-13
5352ThemeUse AtlantaFX style classes before custom CSSAtlantaFX exposes utility styles that reduce custom CSS driftPrefer Styles constants or documented style classesCreate one-off class names for every button variantsaveButton.getStyleClass().add(Styles.ACCENT);saveButton.getStyleClass().add("blue-button-42");Mediumhttps://mkpaz.github.io/atlantafx/javafx 26active2026-08-13
5453ThemeTreat AtlantaFX as a base not the whole design systemAtlantaFX modernizes controls but enterprise UX still needs layout density and workflow rulesDefine app shell navigation table density form and validation conventionsAssume theme choice alone solves enterprise usabilityroot.getStyleClass().add("enterprise-shell");only set PrimerLight and stopHighhttps://mkpaz.github.io/atlantafx/javafx 26active2026-08-13
5554IconsUse Ikonli for consistent enterprise iconsIcon fonts integrate cleanly with JavaFX controls and avoid emoji-style UIUse FontIcon with semantic style classesUse emoji as toolbar or menu iconsButton refresh = new Button("Refresh", new FontIcon("mdi2r-refresh"));new Button("Refresh")Mediumhttps://kordamp.org/ikonli/javafx 26active2026-08-13
5655ComponentsUse AtlantaFX controls for common app affordancesAtlantaFX provides useful controls such as Card Message ModalPane Popover and ToggleSwitchUse built-in AtlantaFX controls before adding another dependencyAdd ControlsFX for components AtlantaFX already coversMessage message = new Message("Saved", "Customer updated successfully");new Label("Saved") with ad hoc stylingMediumhttps://mkpaz.github.io/atlantafx/javafx 26active2026-08-13
5756ComponentsAdd ControlsFX only for missing enterprise controlsControlsFX is useful for specialized controls but should stay optionalUse ControlsFX for SpreadsheetView PropertySheet CheckComboBox or StatusBar needsAdd ControlsFX by default before requirements are clearPropertySheet sheet = new PropertySheet(items);implementation "org.controlsfx:controlsfx" with no usageLowhttps://controlsfx.github.io/javafx 26active2026-08-13
5857TestingTest theme-critical flows with TestFXTheme and CSS changes can break focus visibility dialogs and button affordanceUse TestFX for login save validation and modal workflowsOnly inspect AtlantaFX screens manuallyclickOn("#saveButton"); verifyThat(".message", isVisible());manual theme QA onlyMediumhttps://github.com/TestFX/TestFXjavafx 26active2026-08-13
5958ArchitectureUse application shell plus feature workspacesEnterprise JavaFX apps need stable navigation around changing work areasUse BorderPane shell with navigation toolbar and central workspaceReplace the whole Stage for every featureshell.setLeft(navigation); shell.setTop(toolbar); shell.setCenter(workspace);stage.setScene(new Scene(loadFeature()));Highhttps://openjfx.io/javadoc/26/javafx.graphics/javafx/scene/layout/BorderPane.htmljavafx 26active2026-08-13
6059ArchitectureUse MVVM for complex enterprise screensLarge forms and tables need testable state outside the controllerExpose JavaFX properties from view models and bind controls to themPut all screen state and validation in the controlleramountField.textProperty().bindBidirectional(vm.amountProperty());controller.amount = amountField.getText();Highhttps://openjfx.io/javadoc/26/javafx.base/javafx/beans/property/package-summary.htmljavafx 26active2026-08-13
6160ArchitectureInject services into controllersEnterprise controllers should coordinate UI and call application servicesUse a controller factory or DI container for servicesCreate database connections inside FXML controllersloader.setControllerFactory(type -> injector.getInstance(type));new CustomerRepository(new DriverManager(...))Highhttps://openjfx.io/javadoc/26/javafx.fxml/javafx/fxml/FXMLLoader.htmljavafx 26active2026-08-13
6261NavigationUse role-aware navigation modelsMenus toolbars and shortcuts should reflect the same permission modelBuild navigation items from commands with required rolesHide buttons in one place and leave shortcuts enabledcommand.enabledProperty().bind(permissionService.allowed("invoice.approve"));approveButton.setVisible(false);Highhttps://openjfx.io/javadoc/26/javafx.controls/javafx/scene/control/MenuItem.htmljavafx 26active2026-08-13
6362WorkflowRepresent workflow states visiblyApproval and processing screens need clear business state signalsUse semantic badges row styles and disabled actions by workflow stateUse only free text status columnsrow.pseudoClassStateChanged(PseudoClass.getPseudoClass("blocked"), item.isBlocked());statusCol.setText("B");Mediumhttps://openjfx.io/javadoc/26/javafx.graphics/javafx/css/PseudoClass.htmljavafx 26active2026-08-13
6463TableViewDesign TableView for high-density enterprise dataEnterprise users scan compare sort filter and act on rows for long periodsUse compact row height clear columns sorting filtering and selection summaryUse card grids for large tabular datasetstable.getStyleClass().add("dense-table"); table.getSortOrder().setAll(updatedAtCol);new TilePane(customerCards)Highhttps://openjfx.io/javadoc/26/javafx.controls/javafx/scene/control/TableView.htmljavafx 26active2026-08-13
6564TableViewKeep row actions predictableInline actions in dense tables should be limited and permission-awareUse context menus or a side detail panel for secondary actionsPlace many buttons in every rowtable.setRowFactory(tv -> { TableRow<Order> row = new TableRow<>(); row.setContextMenu(orderMenu); return row; });row contains Edit Delete Approve Print Email buttonsMediumhttps://openjfx.io/javadoc/26/javafx.controls/javafx/scene/control/ContextMenu.htmljavafx 26active2026-08-13
6665TableViewUse server-side paging for large enterprise datasetsDesktop clients should not load entire enterprise tables into memoryFetch pages or filtered slices from servicesLoad all records and filter in the UIPage<Customer> page = customerService.search(criteria, pageRequest);customerRepository.findAll()Highhttps://openjfx.io/javadoc/26/javafx.controls/javafx/scene/control/Pagination.htmljavafx 26active2026-08-13
6766FormsUse form sections for enterprise data entryLong enterprise forms need grouping and progressive disclosureGroup fields into titled sections with validation summariesPlace dozens of inputs in one unbroken GridPaneTitledPane billing = new TitledPane("Billing", billingForm);new GridPane with 80 controlsMediumhttps://openjfx.io/javadoc/26/javafx.controls/javafx/scene/control/TitledPane.htmljavafx 26active2026-08-13
6867FormsProvide validation summary plus field errorsEnterprise forms often need multiple corrections before submissionShow a summary at top and field-level messages near controlsShow only one modal alert after Savesummary.setItems(vm.validationErrors()); field.pseudoClassStateChanged(INVALID, fieldError);new Alert(ERROR, "Invalid form").showAndWait();Highhttps://openjfx.io/javadoc/26/javafx.graphics/javafx/css/PseudoClass.htmljavafx 26active2026-08-13
6968TasksMake long operations cancellableEnterprise imports exports sync and reports need cancel pathsExpose cancel button bound to Task running stateForce users to wait or kill the appcancelButton.setOnAction(e -> task.cancel());runReportButton.setDisable(true);Highhttps://openjfx.io/javadoc/26/javafx.graphics/javafx/concurrent/Task.htmljavafx 26active2026-08-13
7069TasksSurface retryable errors without losing contextNetwork and service failures should preserve user input and next actionShow inline retry messages and keep form/table stateClear the screen on service failuremessage.setDescription("Could not save. Check connection and retry.");loadErrorScene();Highhttps://openjfx.io/javadoc/26/javafx.controls/javafx/scene/control/Label.htmljavafx 26active2026-08-13
7170AuditLog business actions through servicesEnterprise desktop apps need traceability for sensitive changesRecord user action entity result and timestamp in service layerLog only UI button clicksaudit.log(user, "invoice.approve", invoiceId, SUCCESS);System.out.println("clicked approve");Mediumhttps://docs.oracle.com/en/java/javase/26/docs/api/java.logging/java/util/logging/Logger.htmljavafx 26active2026-08-13
7271ConfigurationSeparate user preferences from application configEnterprise apps need deploy-time config and per-user preferencesUse config files for endpoints and Preferences for UI choicesHard-code environment URLs and window statePreferences.userNodeForPackage(App.class).put("theme", "dark");private static final String API = "http://localhost:8080";Mediumhttps://docs.oracle.com/en/java/javase/26/docs/api/java.prefs/java/util/prefs/Preferences.htmljavafx 26active2026-08-13
7372DeploymentPackage resources and themes inside the runtime imageAtlantaFX app CSS icons and FXML must be available after jpackageLoad resources from classpath or module resourcesLoad theme files from developer machine pathsgetClass().getResource("/css/app.css").toExternalForm();new File("src/main/resources/css/app.css").toURI()Highhttps://openjfx.io/openjfx-docs/#modularjavafx 26active2026-08-13
7473DeploymentWrite logs to user-writable locationsInstalled desktop apps may not write inside the application directoryUse platform-specific user data directories for logs and cacheWrite logs beside the executablePath logs = appData.resolve("logs/app.log");Path.of("app.log")Mediumhttps://docs.oracle.com/en/java/javase/26/docs/api/java.base/java/nio/file/Path.htmljavafx 26active2026-08-13
7574TestingCover enterprise happy path and failure pathEnterprise UI tests should verify save validation permission and service failure flowsUse TestFX for core workflows and service fakesOnly test controller methods without UI interactionclickOn("Save"); verifyThat("Customer saved", isVisible());controller.save(); assertTrue(saved);Highhttps://openjfx.io/javadoc/26/javafx.graphics/javafx/robot/Robot.htmljavafx 26active2026-08-13
7675DependenciesKeep optional UI libraries behind actual needsAtlantaFX should be default but additional libraries should be justifiedStart with JavaFX AtlantaFX Ikonli TestFX and add ControlsFX only for missing controlsAdopt many UI libraries at project startdependencies { implementation("io.github.mkpaz:atlantafx-base:2.1.0") }implementation controlsfx gemsfx tilesfx materialfx all at onceMediumhttps://mkpaz.github.io/atlantafx/getting-started/javafx 26active2026-08-13