tags:

views:

168

answers:

4

Hi, I am trying something very basic: I have a list of 5 buttons. They are in a FlowLayout and the general idea should be that once I click one it should disappear and the others should reorder themselves accordingly.

Now, if I call setVisible(false) the button becomes invisible, but it still occupies it's space in the Layoutmanager.

Is there any way to keep the Button in the JPanel while hiding it so it doesn't get picked up by Layout?

Update:: Thanks for all the answers, the problem with removing the buttons is that the order is important. The problem I was trying to solve was a find as you type szenario where a very long list of buttons gets filtered down to only the ones matching the characters entered so users can easily click them. Since users can delete characters from the search field ordering is important and buttons have to pop back in once they match again.

A: 

You could override each button's getPreferredSize() methods (and possibly getMinimumSize() as well to return 0,0 when the component is invisible; and you need to call, I think, invalidate() (or revalidate or validate, I can never keep them straight) on the container.

Carl Smotricz
The problem is that the space that FlowLayout puts between components will be present twice, so there will still be a noticeable gap.
Michael Borgwardt
Right you are! I hadn't thought of that, thanks.
Carl Smotricz
+1  A: 

I see two possibilities:

  • Write your own layout manager that listens for changes to its children's visible property - shouldn't be too hard, you can probably subclass FlowLayout to do it.
  • actually remove the clicked-button from the panel and, if necessary, re-add it later.
Michael Borgwardt
+1  A: 

Just remove it:

 panel.remove( button );

What's wrong with this option?

Layout managers are thought precisely to avoid having the "user" to make tricks in order to have each component it the right place ( although it seems to provoke the opposite effect )

Removing the button from the panel will have the effect of laying out again all the remaining components. That's why it's name is "Layout manager" it manages to layout the components for you.

OscarRyz
+2  A: 

Works fine for me.

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

public class FlowLayoutInvisible extends JFrame
    implements ActionListener
{
    JPanel north;
    int i;

    public FlowLayoutInvisible()
    {

     north = new JPanel();

     for (int i = 0; i < 5; i++)
     {
      JButton button = new JButton("North - " + i);
      button.addActionListener(this);
      north.add(button);
     }

     getContentPane().add(north, BorderLayout.NORTH);
        }

    public void actionPerformed(ActionEvent e)
    {
     Component c = (Component)e.getSource();
     c.setVisible(false);
 ((JPanel)c.getParent()).revalidate();
    }

    public static void main(String[] args)
    {
     FlowLayoutInvisible frame = new FlowLayoutInvisible();
     frame.setDefaultCloseOperation( EXIT_ON_CLOSE );
     frame.pack();
     frame.setLocationRelativeTo( null );
     frame.setVisible(true);
    }
}

If you need more help post your SSCCE.

Update: I don't know if the revalidate() is required. I seemed to have a problem once but now I can't duplicate the problem.

camickr