I was trying to create a GUI and found some curious behavior of java.awt.Component. I wanted to setVisible(true)
/setVisible(false)
an java.awt.Component by an external Event. But this only works when the to be switched Component was already visible in the first place. Attached, I provided a minimal replica of my problem.
package test; import java.awt.Button; import java.awt.Dimension; import java.awt.Frame; import java.awt.Menu; import java.awt.MenuBar; import java.awt.MenuItem; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; public final class Test { public static void main(String[] args) { Button testButton = new Button("Test Button"); testButton.setVisible(false); /* Removing this line makes the code to work as intended, but why? */ Frame mainFrame = new Frame("Test"); mainFrame.setMinimumSize(new Dimension(640, 480)); mainFrame.setVisible(true); mainFrame.addWindowListener(new WindowAdapter() { public void windowClosing(WindowEvent event) { System.exit(0); } }); mainFrame.add(testButton); mainFrame.setMenuBar(new MenuBar()); mainFrame.getMenuBar().add(new Menu("Test")); mainFrame.getMenuBar().getMenu(0).add(new MenuItem("Show/Hide "Test Button"")); mainFrame.getMenuBar().getMenu(0).getItem(0).addActionListener(new ActionListener() { public void actionPerformed(ActionEvent arg0) { if(testButton.isVisible()) testButton.setVisible(false); else testButton.setVisible(true); System.out.println("testButton.getBounds()" + testButton.getBounds()); /* EDIT: Added this line for debugging. */ System.out.println("testButton.isVisible() " + testButton.isVisible()); } }); } }
When you remove line testButton.setVisible(false);
, testButton is viewable and also switchable in its state of visibility, otherwise not. Does anyone know why? Maybe the layout-manager doesn’t work with invisible components?
EDIT: It seems the layout-manager doesn’t setBounds(...)
for invisible components, but why?
Advertisement
Answer
Maybe the layout-manager doesn’t work with invisible components?
Correct, it depends on the rules of the layout manager.
For example the FlowLayout and BoxLayout, ignore invisible components when doing the layout. However, a GridLayout will reserve space.
When using Swing changing a property of a component should automatically invoke the layout manager. So invoking setVisible() should cause a new layout.
However, if layout is not done automatically then you would use code like:
testButton.getParent().revalidate();
I haven’t used AWT for over a decade now but as I recall AWT is not as smart as Swing so you need to use:
testButton.getParent().validate();
after setting the visible state of the button. At least it works in the MRE you provided.