Java.awt.Component的奇怪行为,setVisible(),LayoutManager。

huangapple go评论73阅读模式
英文:

Curious behavior of java.awt.Component, setVisible(), LayoutManager

问题

以下是您提供的代码的翻译部分:

我试图创建一个GUI并发现了java.awt.Component的一些奇怪行为我想通过外部事件对java.awt.Component使用`setVisible(true)`/`setVisible(false)`。但只有当要切换的组件在第一次出现时已经可见才起作用附上我问题的最小复制版

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("测试按钮");
        testButton.setVisible(false); /* 移除此行使代码按预期工作,但为什么? */

        Frame mainFrame = new Frame("测试");
        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("测试"));
        mainFrame.getMenuBar().getMenu(0).add(new MenuItem("显示/隐藏 \"测试按钮\""));
        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()); /* 编辑:为调试添加了这一行。 */
                System.out.println("testButton.isVisible() " + testButton.isVisible());
            }
        });
    }
}
当您移除`testButton.setVisible(false);`这一行时testButton是可见的也可以切换其可见状态否则不行有人知道为什么吗也许布局管理器不适用于不可见的组件

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

请注意,以上只是您提供的代码的翻译部分,如有需要,您可以使用这些翻译来处理您的工作。如果您有任何其他问题或需要进一步帮助,请随时提问。

英文:

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?

答案1

得分: 1

> 或许布局管理器不适用于不可见组件?

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

例如,FlowLayout 和 BoxLayout 在进行布局时会忽略不可见组件。然而,GridLayout 会保留空间。

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

然而,如果布局不是自动执行的,你需要使用类似以下的代码:

testButton.getParent().revalidate();

我已经十多年没有使用 AWT 了,但我记得 AWT 不如 Swing 聪明,所以在设置按钮的可见状态后,你需要使用:

testButton.getParent().validate();

至少在你提供的最小重现环境中是有效的。

英文:

> 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.

huangapple
  • 本文由 发表于 2020年10月10日 20:24:23
  • 转载请务必保留本文链接:https://go.coder-hub.com/64293372.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定