java.awt.Component、setVisible()、LayoutManager的奇怪行为



我试图创建一个GUI,发现java.awt.Component有一些奇怪的行为。我想通过外部事件setVisible(true)/setVisible(false)一个java.awt.Component。但只有当要切换的组件一开始就可见时,这才有效。在附件中,我提供了我的问题的最小副本。

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());
}
});
}
}

删除行testButton.setVisible(false);时,testButton是可见的,并且在其可见状态下也是可切换的,否则就不可切换。有人知道为什么吗?也许布局管理器不处理不可见的组件?

编辑:布局管理器似乎没有为不可见的组件setBounds(...),但为什么?

也许布局管理器不处理不可见的组件?

正确,这取决于布局管理器的规则。

例如FlowLayout和BoxLayout,在进行布局时忽略不可见的组件。但是,GridLayout将保留空间。

当使用Swing时,更改组件的属性应该自动调用布局管理器。因此,调用setVisible((应该会导致一个新的布局。

然而,如果布局不是自动完成的,那么您将使用以下代码:

testButton.getParent().revalidate();

我已经十多年没有使用AWT了,但我记得AWT不如Swing智能,所以你需要使用:

testButton.getParent().validate();

在设置按钮的可见状态之后。至少它在您提供的MRE中有效。

最新更新