2

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

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

4

2 回答 2

2

尝试重新验证您的 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 线程规则。

于 2013-04-01T19:21:55.463 回答
2

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

于 2013-04-01T19:28:39.737 回答