If you want to replace one component with another, you can remove the old component from the container, and add another, something like:
remove(webPanel); add(jbarPanel, BorderLayout.CENTER); repaint(); // запросить перерисовку контейнера
If you need to place one component over another, you can use javax.swing.JLayeredPane . It allows you to place components at different levels (set Integer, the more, the higher). You can place the panel with the browser on the lower level, and the transparent panel with the progress bar on the top, and change the visibility of the top panel as needed.
public class JLayeredPaneExample { static void initUi() { JFrame frame = new JFrame( "JLayeredPaneExample"); frame.setDefaultCloseOperation( WindowConstants.EXIT_ON_CLOSE ); // Панель с содержимымы, поверх которого нужно будет выставлять прогрессбар JPanel background = new JPanel( new BorderLayout() ); background.add( new JTextArea(), BorderLayout.CENTER ); background.add( new JButton("Button"), BorderLayout.SOUTH ); // прозрачная панель с прогрессбаром по центру JPanel glasspane = new JPanel( new GridBagLayout() ); JProgressBar bar = new JProgressBar(0, 100); glasspane.add( bar, new GridBagConstraints() ); glasspane.setOpaque( false ); // чтобы сквозь панель нельзя было кликнуть, ей задается слушатель glasspane.addMouseListener( new MouseAdapter() {} ); // создается JLayeredPane JLayeredPane layeredPane = new JLayeredPane(); // устанавливаем компоненты, чем больше второй параметр (номер слоя), // тем "выше" компонент. // обратите внимание, что номер слоя должен быть объектом Integer // поэтому используется либо метод с тремя параметрами и автобоксинг // или приведение к Integer явно layeredPane.add( background, JLayeredPane.DEFAULT_LAYER, -1 ); layeredPane.add( glasspane, JLayeredPane.DEFAULT_LAYER + 50, -1 ); // JLayeredPane не содержит Layout (а если поставить, то layout будет // выравнивать компоненты в одной плоскости, поэтому нужно задавать // размеры и положение компонентов самостоятельно. // В данном случае панелям ставится размер layeredpane. layeredPane.addComponentListener( new ComponentAdapter() { @Override public void componentResized(ComponentEvent e) { background.setSize( e.getComponent().getSize() ); glasspane.setSize( e.getComponent().getSize() ); } }); JPanel contentPane = new JPanel( new BorderLayout() ); contentPane.add( layeredPane, BorderLayout.CENTER ); contentPane.add( new JButton( "Frame button" ), BorderLayout.SOUTH ); frame.setContentPane( contentPane ); Timer t = new Timer( 1000, (event) -> { glasspane.setVisible( !glasspane.isVisible() ); bar.setValue( bar.getValue() + 5 ); } ); t.start(); frame.setSize( 800, 600 ); frame.setVisible( true ); } public static void main(String[] args) { SwingUtilities.invokeLater( JLayeredPaneExample::initUi ); } }
Also with Java 7, you can use javax.swing.JLayer , which can be hung on any Swing component, to draw over or intercept events. The example draws the word “Load” in the middle of the decorated component and blocks the component from receiving mouse and keyboard events:
static class OverlayUi<V extends Component> extends LayerUI<V> { private boolean visible = false; private JLayer<?> layer; public void setVisible( boolean visible ) { this.visible = visible; if (layer != null) layer.repaint(); } @Override public void eventDispatched(AWTEvent e, JLayer<? extends V> l) { if ( visible ) { // если оверлей виден, он перехватывает события if (e instanceof InputEvent) { ((InputEvent) e).consume(); } } else { super.eventDispatched(e, l); } } @Override public void installUI( JComponent c ) { // вызывается при установке super.installUI(c); layer = (JLayer<?>) c; layer.setLayerEventMask( // указываем события, которые хотим перехватывать AWTEvent.MOUSE_EVENT_MASK | AWTEvent.KEY_EVENT_MASK | AWTEvent.MOUSE_MOTION_EVENT_MASK ); } @Override public void paint( Graphics g, JComponent c ) { super.paint( g, c ); // отрисовка собственно компонента if ( !visible ) return; // если не виден, то ничего больше не рисует g.setFont( c.getFont().deriveFont( 20f ) ); String text = "Загрузка..."; Rectangle2D stringBounds = g.getFontMetrics().getStringBounds( text, g ); int x = (int)((c.getWidth() - stringBounds.getWidth())/2); int y = (int)((c.getHeight() - stringBounds.getHeight())/2); g.drawString( text, x, y ); } } // использование в предыдущем примере: OverlayUi<JPanel> overlayUi = new OverlayUi(); JLayer<JPanel> panelOverlay = new JLayer<JPanel>(background, overlayUi ); contentPane.add( panelOverlay, BorderLayout.CENTER ); overlayUi.setVisible( true );
The tutorial on the Oracle website has an example with an animated loading indicator.