不可调整大小的窗口边框和定位

8
如果我创建了不可调整大小的JFrame窗口,并且启用了Windows Aero,则setLocation似乎无法正确考虑窗口边框。
在以下代码中,我希望第二个窗口被定位到第一个窗口的右侧,然而边框却重叠了。如果禁用Aero或者删除对setResizable的调用,则会按预期执行。
import java.awt.Rectangle;
import javax.swing.JFrame;
public class FrameBorders {
public static void main(String[] args) {
    JFrame frame1 = new JFrame("frame 1");
    JFrame frame2 = new JFrame("frame 2");

    frame1.setResizable(false);
    frame2.setResizable(false);

    frame1.setVisible(true);        
    Rectangle bounds = frame1.getBounds();      
    frame2.setLocation(bounds.x+bounds.width, bounds.y);
    frame2.setVisible(true);

}
}

我是做错了什么还是这是一个 bug?如何同时显示两个不可调整大小的对话框,而不会有重叠的边框?
编辑:添加了截图(也将 frame2 更改为 JDialog 而不是 JFrame)
开启 Aero: Aero On 关闭 Aero: Aero Off 开启 Aero 且可调整大小: Aero On but resizable

2
请不要在一个不可调整大小的容器上设置任意边界。参见The Use of Multiple JFrames, Good/Bad Practice? - trashgod
当您设置JFrame#getRootPane()。setBorder(someBorder)时会发生什么,因为Aero在底部和左侧有阴影。 - mKorbel
@mKorbel 对边框进行设置会设置内部边框,但不会影响窗口边框。 - msam
@mKorbel 不太确定我是否理解了,但是我能获取到这个额外边框的大小信息吗? - msam
抱歉,我现在使用的是WinXp,无法使用Win7。只能等待。但为了让其他读者更好地理解,我会在这里发布两张开启和关闭Areo的截图。 - mKorbel
显示剩余4条评论
2个回答

7
在不可调整大小的容器上设置边界的问题是什么?
假设你调整了边界使其在你的平台上看起来很好。假设用户所用平台的字体具有不同(比如更大)的FontMetrics。尽管这个例子有些牵强,但你可以理解这个想法。如果你改变一个不可调整大小的容器的边界,请确保任何文本都能在主机平台默认字体下显示。 image
import java.awt.BorderLayout;
import java.awt.EventQueue;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;

/**
 * @see https://dev59.com/UGjWa4cB1Zd3GeqPtLXa#12532237
 */
public class Evil extends JPanel {

    private static final String s =
        "Tomorrow's winning lottery numbers: 42, ";
    private JLabel label = new JLabel(s + "3, 1, 4, 1, 5, 9", JLabel.LEFT);

    public Evil() {
        this.add(label);
    }

    private void display() {
        JFrame f = new JFrame("Evil");
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        f.add(this, BorderLayout.WEST);
        f.pack();
        int w = SwingUtilities.computeStringWidth(
            label.getFontMetrics(label.getFont()), s);
        int h = f.getHeight();
        f.setSize(w, h);
        f.setResizable(false);
        f.setLocationRelativeTo(null);
        f.setVisible(true);
    }

    public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {

            @Override
            public void run() {
                new Evil().display();
            }
        });
    }
}

就调整大小而言,这是一个很好的观点(如果单独考虑,这将是我在评论中提出的问题的好答案)。然而,我的原始问题是有关定位的。假设使用pack() /没有文本/大小不会改变甚至是空白的对话框/框架,就像在我自己编造的示例中一样。 - msam
1
尝试使用 pack(),它会“使该Window的大小适合其子组件的首选大小和布局。”抱歉,我不使用Aero;一个展示您描述的问题的 sscce 可能会有所帮助。 - trashgod
在这种情况下,pack() 没有任何区别,因为窗口是空的(这就是我没有在我的示例中包含它的原因)。修改了代码使其可编译(仅添加了导入和主类...)。如果您不使用 Aero,则不会遇到此代码问题,因为此问题仅与 Aero 有关(请参见截屏)。 - msam

5
似乎这不是Java问题,而是Aero Appcompat的问题,如此处所述
我在Java中看到的一个解决方案是让窗口可调整大小,然后解决setMaximumSize bug

好的链接;该平台拥有框架装饰,因此结果并不完全令人震惊;“aqua”也有类似的异常情况。 - trashgod

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接