【问题标题】:getPreferredSize() only called twice after pack()getPreferredSize() 在 pack() 之后只调用了两次
【发布时间】:2013-04-01 19:15:41
【问题描述】:

为什么在JFrame 上调用pack() 时,getPreferredSize() 只被调用两次,如下例所示:

public class PackTest {
    static JFrame f = new JFrame();
    @SuppressWarnings("serial")
    public static void main(String[] args) {
        f.add(new JPanel() {
            int i = 0;
            @Override
            public Dimension getPreferredSize() {
                System.out.println("getPreferredSize() called");
                if(i++ >= 2)
                    return new Dimension(200, 200); // This is never returned
                else
                    return new Dimension(100, 100);
            }
        });
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        f.pack();
        f.setVisible(true);
        for(int i = 0; i < 10; i++) {
            try {
                TimeUnit.SECONDS.sleep(1);
            } catch(InterruptedException e) {}
            SwingUtilities.invokeLater(new Runnable() {
                @Override
                public void run() {
                    System.out.println("Calling pack()");
                    f.pack();
                }
            });
        }
    }
}

似乎getPreferredSize() 只在它不断返回不同的东西时才被调用(即,如果它每次返回不同的维度,在示例中它将被调用 10 次)。为什么 Swing 会这样做,我如何让 pack() 正确调整 JFrame 的大小?

【问题讨论】:

    标签: java swing jframe jpanel preferredsize


    【解决方案1】:

    尝试重新验证您的 JPanel 以让它调用它的preferredSize:

    import java.awt.*;
    import java.awt.event.*;
    import javax.swing.*;
    
    public class PackTest {
    
       public static void main(String[] args) {
          SwingUtilities.invokeLater(new Runnable() {
             public void run() {
                createAndShowGui();
             }
          });
       }
    
       public static void createAndShowGui() {
          final JFrame f = new JFrame();
          final JPanel panel = new JPanel() {
             int i = 0;
    
             @Override
             public Dimension getPreferredSize() {
                System.out.println("getPreferredSize() called");
                if (i++ >= 2)
                   return new Dimension(200, 200); // This is never returned
                else
                   return new Dimension(100, 100);
             }
          };
          f.add(panel);
          f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
          f.pack();
          f.setVisible(true);
    
          int delay = 1000;
          new Timer(delay, new ActionListener() {
    
             @Override
             public void actionPerformed(ActionEvent arg0) {
                System.out.println("Calling pack()");
                panel.revalidate();
                f.pack();
             }
          }).start();
       }
    }
    

    顺便说一句,您需要确保在您的真实代码中努力遵守 Swing 线程规则。

    【讨论】:

      【解决方案2】:

      getPreferredSize() 总是在父容器调整大小或重新验证时调用。无论此方法返回的Dimension 值是什么,它都会对组件(如果被覆盖)强制执行固定大小,无论窗口和其他组件的大小如何,它都不应更改。

      【讨论】:

      • pack() 在示例中被调用了 10 次,而 getPreferredSize() 只被调用了两次。
      猜你喜欢
      • 2023-03-27
      • 2015-11-28
      • 1970-01-01
      • 2011-10-16
      • 1970-01-01
      • 2016-06-20
      • 1970-01-01
      • 1970-01-01
      • 2011-12-06
      相关资源
      最近更新 更多