为什么getPreferredSize()
仅在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
的大小?
答案 0 :(得分: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线程规则。
答案 1 :(得分:2)
getPreferredSize()
。无论此方法返回的Dimension
值是什么,它都会对组件强制执行固定大小(如果被覆盖),无论窗口大小和其他组件如何,都不应更改。