java - getPreferredSize() 在 pack() 之后仅调用两次

标签 java swing jframe jpanel preferredsize

为什么在 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 的大小?

最佳答案

尝试重新验证您的 JPanel 以使其调用其首选尺寸:

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 线程规则。

关于java - getPreferredSize() 在 pack() 之后仅调用两次,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15750092/

相关文章:

java - Firebase 搜索功能

java - 双向一对一映射到多个字段

java - Spark Java 使用数学运算来获取具有最大截止值的值比例

java - 在DB中删除或插入后如何触发Jtable更新?

java - 在jlist中添加图片

java - 为什么JFrame的update、revalidate、repaint不更新窗口?

java - 反序列化问题

java - 检索 JTabbedpane 中 Textarea 的内容

java - 如何在具有 GridLayout 的 JPanels 中居中对齐所有内容

java - 加载屏幕 - JFrame 从其他类中设置可见