我正在使用Java制作一个游戏,需要弄清如何相对于最大化大小调整JFrame的大小。在阅读了Hovercraft full of Eel的回答并进行了一些实验后,我已经更新了代码。以下应该是一个最小、完整和可验证的示例:
import java.awt.Dimension;
import javax.swing.*;
import java.awt.Toolkit;
import java.lang.reflect.InvocationTargetException;
public class MyFrameTest {
JFrame frame;
public static void main(String[] args) {
new MyFrameTest();
}
public MyFrameTest() {
System.out.println("screenSize: " + Toolkit.getDefaultToolkit().getScreenSize());
try {
SwingUtilities.invokeAndWait(new Runnable() {
public void run() {
frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.setVisible(true);
}
});
}
catch (Exception e) { System.out.println("invokeAndWait exception: "+e); }
set_size(300,300);
set_size(500,500);
set_size(0,0);
set_size(0,0);
set_size(500,500);
set_size(0,0);
set_size(0,0);
System.exit(0);
}
public void set_size(int width, int height) {
final Dimension d = new Dimension(width, height);
final int w = width;
final int h = height;
try { Thread.sleep(500); } catch (InterruptedException e) { }
try {
SwingUtilities.invokeAndWait(new Runnable() {
public void run() {
if (w == 0 && h == 0) {
frame.setExtendedState(JFrame.MAXIMIZED_BOTH);
} else {
frame.setExtendedState(JFrame.NORMAL);
frame.setSize(d);
}
displaySize(frame, w, h);
}
});
} catch (Exception e) { System.out.println("invokeAndWait exception: "+e); }
}
public void displaySize(JFrame frame, int width, int height) {
Dimension df = frame.getSize();
Dimension dc = frame.getContentPane().getSize();
if (width == 0 && height == 0)
System.out.printf("Size maximized : Frame %4d,%-4d : Content %4d,%-4d\n",
df.width, df.height, dc.width, dc.height);
else
System.out.printf("Size %4d,%-4d : Frame %4d,%-4d : Content %4d,%-4d\n",
width, height, df.width, df.height, dc.width, dc.height);
}
}
我正在Linux上开发,这是我得到的输出:
screenSize: java.awt.Dimension[width=1920,height=1080]
Size 300,300 : Frame 300,300 : Content 2,1
Size 500,500 : Frame 500,500 : Content 292,270
Size maximized : Frame 500,500 : Content 492,470
Size maximized : Frame 1928,1033 : Content 1920,1003
Size 500,500 : Frame 500,500 : Content 1920,1003
Size maximized : Frame 500,500 : Content 492,470
Size maximized : Frame 1928,1033 : Content 1920,1003
当我设置为非最大化大小时,框架的大小是正确的,但如果我将其最大化,第一次检查框架大小时不会显示任何差异。只有第二次设置和查询时才会显示出来。
奇怪的是,如果我连续两次设置它如下:
if (w == 0 && h == 0) {
frame.setExtendedState(JFrame.MAXIMIZED_BOTH);
frame.setExtendedState(JFrame.MAXIMIZED_BOTH);
} else {
无论我调用多少次,它都从不更新框架大小。如果我连续设置三次,它就有效了。也许这是一个切换开关?
更奇怪的是,ContentPane 大小滞后于框架大小,这意味着它滞后于最大化大小两个尝试。
在操作程序时,我设法获得了一种组合,在连续运行时表现随机,有时会立即更新,有时则不会。这使我认为在 EDT 中可能存在线程时间问题,也许它是懒惰更新,但添加更长的休眠并没有帮助。
在 Windows 上输出如下:
screenSize: java.awt.Dimension[width=1600,height=900]
Size 300,300 : Frame 300,300 : Content 116,0
Size 500,500 : Frame 500,500 : Content 284,262
Size maximized : Frame 1616,854 : Content 484,462
Size maximized : Frame 1616,854 : Content 1600,816
Size 500,500 : Frame 500,500 : Content 1600,816
Size maximized : Frame 1616,854 : Content 484,462
Size maximized : Frame 1616,854 : Content 1600,816
在这里JFrame的大小是正确的,但是ContentPane仍然落后于框架。