Ocultar um componente oscilante sem revalidar o layout?

Se eu configurar um JFrame com alguns componentes e um gerenciador de layout, que inicialmente parece perfeitamente bem e, posteriormente, devido a alguma condição (digamos, clicando em um botão), oculto um desses componentes - o gerenciador de layout embaralha todos os componentes novamente .

Veja o código de exemplo - inicialmente 3 botões aparecem. Quando você clica no botão Ocultar, o botão Ocultar fica oculto - mas os dois botões externos se comprimem. Quando você clica no botão Mostrar, eles se separam novamente para criar espaço. Como posso impedir que isso aconteça, para que, depois de chamar o pack (), os componentes permaneçam onde estão, independentemente de se tornarem ocultos posteriormente?

No meu código real, estou fazendo isso com GridBagLayout, mas usei FlowLayout no exemplo abaixo, porque é mais simples e menos código, e mostra exatamente o mesmo comportamento.

Só consigo pensar em maneiras desagradáveis de fazer isso, como usar .setEnabled (false) em vez de .setVisible (false) e substituir o método paintComponent () do componente para não desenhar o componente quando ele estiver desabilitado.

Parece o problema exatamente oposto ao aqui -Ocultar um botão do Layout no Java Swing - onde está reclamando que botões ocultosFaz ainda ocupam espaço :) Mas não há código de amostra para mostrar que funciona dessa maneira.

Muito obrigado por todas as sugestões :)

Exemplo:

import java.awt.FlowLayout;
import java.awt.event.ActionEvent;

import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;

public class RevalidateWhenSetChildInvisibleExample
{
    private JButton button1;
    private JButton button2;
    private JButton button3;

    public void run ()
    {
        // Set up action
        Action hideButtonAction = new AbstractAction ()
        {
            @Override
            public void actionPerformed (ActionEvent e)
            {
                button2.setVisible (false);
            }
        };
        hideButtonAction.putValue (Action.NAME, "Hide");

        Action showButtonAction = new AbstractAction ()
        {
            @Override
            public void actionPerformed (ActionEvent e)
            {
                button2.setVisible (true);
            }
        };
        showButtonAction.putValue (Action.NAME, "Show");

        // Set up buttons
        button1 = new JButton ("Dummy");
        button2 = new JButton (hideButtonAction);
        button3 = new JButton (showButtonAction);

        // Set up content pane
        JPanel contentPane = new JPanel ();
        contentPane.setLayout (new FlowLayout ());
        contentPane.add (button1);
        contentPane.add (button2);
        contentPane.add (button3);

        // Set up frame
        JFrame frame = new JFrame ();
        frame.setContentPane (contentPane);
        frame.pack ();
        frame.setVisible (true);
    }

    public static void main (String args [])
    {
        SwingUtilities.invokeLater (new Runnable ()
        {
            public void run ()
            {
                new RevalidateWhenSetChildInvisibleExample ().run ();
            }
        });
    }
}