Java .setVisible(true)立即重新绘制
在一个简短的方法中,我使用setVisible(false)隐藏JFrame。 然后我截图并用setVisible(true)恢复JFrame 在再次显示后,窗口应该显示与以前不同的图片(比如说拍摄的部分屏幕截图) 问题是,在调用setVisible(true)之后,在调用paintComponent并绘制更新状态之前,窗口会以旧内容闪烁一秒钟 我可能会用一种丑陋的方式来解决这个问题,但我想知道是否有更好的解决方案 提前谢谢你的帮助 编辑:在准备一个示例时,我注意到,如果不像我在程序中那样使用透明度,效果几乎无法观察到。我应该提到这一点。以下是我的想法:Java .setVisible(true)立即重新绘制,java,swing,transparency,visibility,repaint,Java,Swing,Transparency,Visibility,Repaint,在一个简短的方法中,我使用setVisible(false)隐藏JFrame。 然后我截图并用setVisible(true)恢复JFrame 在再次显示后,窗口应该显示与以前不同的图片(比如说拍摄的部分屏幕截图) 问题是,在调用setVisible(true)之后,在调用paintComponent并绘制更新状态之前,窗口会以旧内容闪烁一秒钟 我可能会用一种丑陋的方式来解决这个问题,但我想知道是否有更好的解决方案 提前谢谢你的帮助 编辑:在准备一个示例时,我注意到,如果不像我在程序中那样使用透
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Toolkit;
import javax.swing.JFrame;
import javax.swing.JPanel;
import com.sun.awt.AWTUtilities;
public class Test {
static boolean flag = false;
static Dimension scrSize = Toolkit.getDefaultToolkit().getScreenSize();
public static void main(String[] args) throws InterruptedException {
JFrame frame = new JFrame();
frame.setUndecorated(true);
AWTUtilities.setWindowOpaque(frame, false); //draw on a transparent window
frame.setSize(scrSize.width, scrSize.height);
frame.setContentPane(new JPanel() {
protected void paintComponent(Graphics g)
{
if (Test.flag) {
g.setColor(Color.RED);
g.drawRect(50, 50, scrSize.width - 100, scrSize.height - 100);
}
else {
g.setColor(Color.GREEN);
g.fillOval(50, 50, scrSize.width - 100, scrSize.height - 100);
}
}
});
frame.setVisible(true); //green oval shown
Thread.sleep(1000);
frame.setVisible(false);
flag = true; // next draw produces red rectangle
Thread.sleep(1000);
frame.setVisible(true); // before the next draw,
// you can see a flash of the green oval
}
}
这是因为每个AWT窗口都有一个与屏幕图像同步的屏幕外图像。显示窗口时,其内容直接从屏幕外图像绘制。这发生在toolkit线程上,而不是事件分派线程上 只有在显示窗口后,帧才会在事件分派线程上重新绘制 在Java1.6之前,AWT中没有每窗口双缓冲,因此您可能会看到一个灰色背景,这就是臭名昭著的“灰色矩形”问题
我知道的唯一解决方法是每次创建一个新的帧。您可以重复使用旧框架的内容面板,因此开销不会太高。我意识到这个答案是在提出问题一年后提出的,但我也遇到了类似的问题,当然在尝试解决它之前也做了一些研究。对于遇到此问题的任何人,请尝试在打包前处理您的窗口/框架并使其可见。在框架再次可见之前设置图像。确保代码在事件分派线程上执行。如果您需要更多帮助,请发布您的日志。使用
EventQueue.invokeLater()
对更改进行排序。无法重现,是进行SSCE的时候了,正如@camickr已经建议的那样听起来有点合理-只是:我根本无法重现问题。因此,在使用新创建的框架之前,我建议找出真正的原因:-)它只会发生在复杂的框架中,并且只有在框架中的某些内容不可见时才发生。我的回答解释了原因。好了,除了创建一个新的框架之外,你什么也做不了。正如我所说的:推理听起来不错,我当然会在再次展示之前更改内容(否则我怎么可能尝试复制)。所以区别可能是复杂的部分,有多复杂?从屏幕外图像显示和绘制框架,然后验证并重新绘制根窗格。根据日志记录的方式,你仍然会看到旧内容一段时间。是的,我理解其中的原因。。。直到我看到它(固执的我:)最终还是会在我的上网本上试用。谢谢这应该是公认的答案。每次显示对话框时都创建一个新框架是不可接受的。您确定可以处理窗口吗?我想我在Oracle文档中读到,这释放了本机资源,只有在完成框架/窗口时才能完成。