当setResizable为false时,窗口在JFrame上的setSize之后移动

时间:2016-05-04 20:37:47

标签: java swing

当我查看Frame.setResizable的文档时,我读到了:

Sets whether this frame is resizable by the user.

所以我理解我仍然可以在其上调用setSize以编程方式调整它。但如果我这样做,框架向下移动! (至少在Ubuntu,Unity下)。如果我希望框架与内容的大小相匹配,这尤其令人讨厌。例如,只需尝试以下SSCCE:

package test;

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.Rectangle;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
import javax.swing.JFrame;
import javax.swing.JTextArea;
import javax.swing.SwingUtilities;
import javax.swing.text.AbstractDocument;
import javax.swing.text.AttributeSet;
import javax.swing.text.BadLocationException;
import javax.swing.text.DocumentFilter;

public class Test2 {
    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                final JFrame mainFrame = new JFrame("test");
                mainFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                mainFrame.setResizable(false);
                final JTextArea field = new JTextArea() {
                    public Dimension getPreferredSize() {
                        Dimension pref = super.getPreferredSize();
                        return new Dimension(Math.max(50, pref.width),Math.max(20, pref.height));
                    }
                };
                ((AbstractDocument)field.getDocument()).setDocumentFilter(new DocumentFilter() {
                    @Override
                    public void replace(DocumentFilter.FilterBypass fb, int offset, int length, String text, AttributeSet attrs) throws BadLocationException {
                        super.replace(fb, offset, length, text, attrs);
                        System.out.println("before "+mainFrame.getLocation().y);
                        mainFrame.pack();
                        System.out.println("after "+mainFrame.getLocation().y+"\n");
                    }
                });
                mainFrame.getContentPane().setLayout(new BorderLayout());
                mainFrame.getContentPane().add(field,BorderLayout.CENTER);
                mainFrame.pack();
                mainFrame.setVisible(true);
            }
        });
    }

}

键入一些字符以使窗口扩展。至少在Unity上,窗口向下移动......我不知道如何解决这个问题。

更新:

上述代码的结果如下:

before 52
after 52

before 80
after 108

before 108
after 108

before 136
after 136

before 164
after 164

before 192
after 192
...

最后,当帧被移动时我不会得到......

如果我在Frame上添加ComponentListener,这是我可以获得的堆栈跟踪:

at test.Test2$1$3.componentMoved(Test2.java:50)
at java.awt.AWTEventMulticaster.componentMoved(AWTEventMulticaster.java:169)
at java.awt.AWTEventMulticaster.componentMoved(AWTEventMulticaster.java:169)
at java.awt.Component.processComponentEvent(Component.java:6345)
at java.awt.Component.processEvent(Component.java:6296)
at java.awt.Container.processEvent(Container.java:2229)
at java.awt.Window.processEvent(Window.java:2022)
at java.awt.Component.dispatchEventImpl(Component.java:4872)
at java.awt.Container.dispatchEventImpl(Container.java:2287)
at java.awt.Window.dispatchEventImpl(Window.java:2719)
at java.awt.Component.dispatchEvent(Component.java:4698)
at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:747)
at java.awt.EventQueue.access$300(EventQueue.java:103)
at java.awt.EventQueue$3.run(EventQueue.java:706)
at java.awt.EventQueue$3.run(EventQueue.java:704)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:77)
at java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:87)
at java.awt.EventQueue$4.run(EventQueue.java:720)
at java.awt.EventQueue$4.run(EventQueue.java:718)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:77)
at java.awt.EventQueue.dispatchEvent(EventQueue.java:717)
at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:242)
at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:161)
at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:150)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:146)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:138)
at java.awt.EventDispatchThread.run(EventDispatchThread.java:91)

它表现得就像我手动移动框架一样。在调整帧大小时,Unity可能正在做某事。

1 个答案:

答案 0 :(得分:3)

  

试试以下SSCCE:

这不是SSCCE(关闭但不完全)。没有main()方法,也没有导入。我们应该能够毫不犹豫地复制/粘贴/编译/测试。

  

键入一些字符以使窗口扩展

在Windows 7上使用JDK8对我很好。

//mainFrame.setSize(mainFrame.getContentPane().getPreferredSize());
mainFrame.pack();

我会使用上面的代码。您将获得更好的框架大小,因为pack()将考虑框架装饰,而不像setSize()方法。

如果pack()无法解决问题,那么我想建议首先保存帧的位置,然后调用setLocation(...)方法,或使用setBounds(...)来完全控制尺寸/位置。

编辑:

  

最后,当移动Frame时我没有得到......

尝试这样的事情:

((AbstractDocument)field.getDocument()).setDocumentFilter(new DocumentFilter()
{
    @Override
    public void replace(DocumentFilter.FilterBypass fb, int offset, int length, String text, AttributeSet attrs) throws BadLocationException
    {
        Point location = mainframe.getLocation();

        super.replace(fb, offset, length, text, attrs);

        mainFrame.pack();

        SwingUtilities.invokeLater(new Runnable()
        {
            public void run()
            {
                mainframe.setLocation( location );
            }
        });
    }
});