您可以通过以下几种方式拖动鼠标来调整JFrame的大小:
除了数字5之外,我的程序正在重新绘制每个动作。
为什么?
这可能是我程序中的错误吗?它似乎并非如此。我不知道我会在哪里为那个特殊情况添加重绘请求......似乎JFrame本身应该在每次调整大小后调用它的contentPane上重绘,对吧?
在JFrame类中,它闻起来像Java本身的一个bug。
SSCCE:
import javax.swing.JFrame;
import javax.swing.SwingUtilities;
class Gui
{
Gui()
{
JFrame masterWindow = new JFrame("My very own SSCCE");
masterWindow.setSize(1100, 100);
masterWindow.setLocationRelativeTo(null);
masterWindow.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
masterWindow.setVisible(true);
}
}
class Main
{
public static void main(String[] args)
{
SwingUtilities.invokeLater(new Runnable()
{
@Override
public void run()
{
new Gui();
}
});
}
}
抓住JFrame的上边缘并将其拖动到屏幕的上边缘并释放。底部延伸部分应为黑色。如果你然后最大化它,它将是灰色的,应该是。
我仍然说这是Java或Windows bug。
答案 0 :(得分:2)
它似乎是Windows的Windows实现中的一个错误。 (我也在使用Windows 7和JDK7。)
当Windows决定更改窗口高度时,Window会收到COMPONENT_MOVED
事件,但不会收到COMPONENT_RESIZED
事件。
在Windows类中,非公开方法dispatchEventImpl()
会通过调用COMPONENT_RESIZED
和invalidate()
来回复validate()
个事件,但会忽略COMPONENT_MOVED
事件
这是一种强制方法,可以在此类事件发生后重新验证窗口。这可能偶尔会使窗口在其他情况下重新验证,但不常见,因为Window类本身在每次COMPONENT_RESIZED
事件后都进行了重新验证,并且报告的错误仅在窗口被主动调整大小时发生。用户。
masterWindow.addComponentListener(new ComponentAdapter() {
private int oldWidth = 0;
private int oldHeight = 0;
@Override
public void componentResized(ComponentEvent e) {
oldWidth = masterWindow.getWidth();
oldHeight = masterWindow.getHeight();
}
@Override
public void componentMoved(ComponentEvent e) {
if (masterWindow.getWidth() != oldWidth || masterWindow.getHeight() != oldHeight) {
masterWindow.invalidate();
masterWindow.validate();
}
oldWidth = masterWindow.getWidth();
oldHeight = masterWindow.getHeight();
}
});
答案 1 :(得分:2)
顺便说一句:也可以通过双击窗口的顶部/底部角落(至少在Windows 8中)调用操作5。
@Enwired:只有在最大化期间实际移动窗口时,您的解决方案才有效。 但是当窗口已经在y = 0时,当调用垂直最大化时,它不起作用。 (我使用一个名为AltDrag的小工具将窗口按到屏幕的边框,这使得这种情况更有可能。但是最初没有移动或重新定位的新窗口可能会遇到同样的问题。)
我注意到,当窗口垂直最大化时,paint()
会在窗口上调用一次。
因此,最大化操作的解决方案是覆盖paint()
并执行此操作:
@Override
public void paint(Graphics g)
{
checkResizeWindow(this);
super.paint(g);
}
public static void checkResizeWindow(Window window)
{
if (!window.isShowing())
{
return;
}
Component[] components = window.getComponents();
if (components.length == 0)
{
return;
}
Component comp = components[0];
Insets insets = window.getInsets();
Dimension innerSize = window.getSize();
innerSize.width -= insets.left + insets.right;
innerSize.height -= insets.top + insets.bottom;
if (!innerSize.equals(comp.getSize()))
{
window.invalidate();
window.validate();
}
}
我使用的计算是通过检查innerSize
与第一个子组件的大小(通常是单个Panel
填写整个{{1}来确定窗口是否确实需要重新验证。 }})。
但是,恢复操作仍然存在同样的原始问题。
我们必须找到一个在这种情况下调用的事件,并在那时调用innerSize
。
我也在考虑......
checkResizeWindow()
方法在重复调用过快时出现问题。checkResizeWindow()
的定期轮询检查,但轮询通常是一个坏概念,并且有它自己的缺点。