diff --git a/CHANGELOG.md b/CHANGELOG.md index 9b73cd09..d55c4f18 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,8 @@ FlatLaf Change Log left/right vertical alignment and running in Java 19+. (issue #746) - CheckBox and RadioButton: Fixed cut off right side when border is removed and horizontal alignment is set to `right`. (issue #734) +- TabbedPane: Fixed NPE when using focusable component as tab component and + switching theme. (issue #745) ## 3.2.1 diff --git a/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatTabbedPaneUI.java b/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatTabbedPaneUI.java index 52bc470c..f235fcf1 100644 --- a/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatTabbedPaneUI.java +++ b/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatTabbedPaneUI.java @@ -3567,7 +3567,7 @@ public class FlatTabbedPaneUI //---- class FlatSelectedTabRepainter ------------------------------------- private static class FlatSelectedTabRepainter - implements PropertyChangeListener//, Runnable + implements PropertyChangeListener { private static FlatSelectedTabRepainter instance; @@ -3617,17 +3617,31 @@ public class FlatTabbedPaneUI break; case "activeWindow": - repaintSelectedTabs( keyboardFocusManager.getPermanentFocusOwner() ); + Component permanentFocusOwner = keyboardFocusManager.getPermanentFocusOwner(); + if( permanentFocusOwner != null ) + repaintSelectedTabs( permanentFocusOwner ); break; } } private void repaintSelectedTabs( Component c ) { - if( c instanceof JTabbedPane ) - repaintSelectedTab( (JTabbedPane) c ); + // Use invokeLater because this method may be invoked while UI update + // is in progress. This may happen if a focusable component (e.g. text field) + // is used as tab component (see JTabbedPane.setTabComponentAt()). + // uninstallTabContainer() removes all components from tabbed pane and + // the text field looses focus. + EventQueue.invokeLater( () -> { + // because this is invoked later, check whether component is still displayable + if( !c.isDisplayable() ) + return; - while( (c = SwingUtilities.getAncestorOfClass( JTabbedPane.class, c )) != null ) - repaintSelectedTab( (JTabbedPane) c ); + if( c instanceof JTabbedPane ) + repaintSelectedTab( (JTabbedPane) c ); + + Component c2 = c; + while( (c2 = SwingUtilities.getAncestorOfClass( JTabbedPane.class, c2 )) != null ) + repaintSelectedTab( (JTabbedPane) c2 ); + } ); } private void repaintSelectedTab( JTabbedPane tabbedPane ) {