private static void showSnapshot( boolean useAlpha, Map<JLayeredPane, JComponent> map ) {
		inShowSnapshot = true;

		// create snapshots for all shown windows
		Window[] windows = Window.getWindows();
		for( Window window : windows ) {
			if( !(window instanceof RootPaneContainer) || !window.isShowing() )
				continue;

			// create snapshot image
			// (using volatile image to have correct sub-pixel text rendering on Java 9+)
			VolatileImage snapshot = window.createVolatileImage( window.getWidth(), window.getHeight() );
			if( snapshot == null )
				continue;

			// paint window to snapshot image
			JLayeredPane layeredPane = ((RootPaneContainer)window).getLayeredPane();
			layeredPane.paint( snapshot.getGraphics() );

			// create snapshot layer, which is added to layered pane and paints
			// snapshot with animated alpha
			JComponent snapshotLayer = new JComponent() {
				@Override
				public void paint( Graphics g ) {
					if( inShowSnapshot || snapshot.contentsLost() )
						return;

					if( useAlpha )
						((Graphics2D)g).setComposite( AlphaComposite.getInstance( AlphaComposite.SRC_OVER, alpha ) );
					g.drawImage( snapshot, 0, 0, null );
				}

				@Override
				public void removeNotify() {
					super.removeNotify();

					// release system resources used by volatile image
					snapshot.flush();
				}
			};
			if( !useAlpha )
				snapshotLayer.setOpaque( true );
			snapshotLayer.setSize( layeredPane.getSize() );

			// add image layer to layered pane
			layeredPane.add( snapshotLayer, Integer.valueOf( JLayeredPane.DRAG_LAYER + (useAlpha ? 2 : 1) ) );
			map.put( layeredPane, snapshotLayer );
		}

		inShowSnapshot = false;
	}
Create a snapshot of the old UI and shows it on top of the UI.
Invoke before setting new look and feel.
flatlaf-extras/src/main/java/com/formdev/flatlaf/extras/FlatAnimatedLafChange.java