只是出于学术兴趣,你可以在手动调整大小时使画布不闪烁。
public class FlickerAWT extends Canvas {
public static void main(String[] args) {
Frame f = new Frame(str);
//this line change nothing
//JFrame f = new JFrame(str);
f.add(new FlickerAWT());
f.pack();
int frameWidth = f.getWidth();
int frameHeight = f.getHeight();
Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
f.setLocation(screenSize.width / 2 - frameWidth / 2, screenSize.height / 2 - frameHeight / 2);
f.setVisible(true);
f.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
System.exit(0);
}
public void windowDeiconified(WindowEvent e) {
}
public void windowIconified(WindowEvent e) {
}
});
}
private Color bgColor; private Color contentColor;
Font f = new Font("Georgia", Font.BOLD, 16);
static String str = "AWT Canvas Resize Flickering";
public FlickerAWT() {
Random r = new Random();
bgColor = new Color(r.nextInt(256), r.nextInt(256), r.nextInt(256));
contentColor = new Color(r.nextInt(256), r.nextInt(256), r.nextInt(256));
}
public Dimension getPreferredSize() {
FontMetrics fm = getFontMetrics(f);
return new Dimension(fm.stringWidth(str) + 20, fm.getHeight() + 10);
}
public void paint(java.awt.Graphics g) {
g.setColor(bgColor);
g.fillRect(0, 0, getWidth(), getHeight());
g.setColor(contentColor);
g.setFont(f);
FontMetrics fm = g.getFontMetrics(f);
int dx = getWidth() / 2 - (fm.stringWidth(str) / 2);
int dy = getHeight() / 2 + (fm.getHeight() / 2);
g.drawString(str, dx, dy);
}
}
您可以在Java编辑器中复制粘贴并运行示例。
答案 0 :(得分:5)
您可以将其添加到main方法的开头,以避免背景闪烁:
System.setProperty("sun.awt.noerasebackground", "true");
答案 1 :(得分:1)
我认为关键是使用双缓冲,可能解决此问题的一种方法是使用默认情况下双缓冲区的Swing:
import java.awt.*;
import java.util.Random;
import javax.swing.*;
public class FlickerSwing extends JPanel {
public static void main(String[] args) {
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
private static void createAndShowGui() {
JFrame f = new JFrame(str);
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.add(new FlickerSwing());
f.setLocationRelativeTo(null);
f.pack();
f.setVisible(true);
}
private Color bgColor;
private Color contentColor;
Font f = new Font("Georgia", Font.BOLD, 16);
static String str = "Swing Resize Flickering";
public FlickerSwing() {
Random r = new Random();
bgColor = new Color(r.nextInt(256), r.nextInt(256), r.nextInt(256));
contentColor = new Color(r.nextInt(256), r.nextInt(256), r.nextInt(256));
setBackground(bgColor);
}
public Dimension getPreferredSize() {
FontMetrics fm = getFontMetrics(f);
return new Dimension(fm.stringWidth(str) + 20, fm.getHeight() + 10);
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.setColor(contentColor);
g.setFont(f);
FontMetrics fm = g.getFontMetrics(f);
int dx = getWidth() / 2 - (fm.stringWidth(str) / 2);
int dy = getHeight() / 2 + (fm.getHeight() / 2);
g.drawString(str, dx, dy);
}
}
答案 2 :(得分:1)
我知道这个问题很古老,但是在我的搜索中出现了,同时我找到了一个解决方案:
有两个问题:
一方面,java.awt.Container的update(...)
方法如下所示:
public void update(Graphics g) {
if (isShowing()) {
if (! (peer instanceof LightweightPeer)) {
g.clearRect(0, 0, width, height);
}
paint(g);
}
}
即。它会在绘制孩子之前调用g.clearRect(...)
来删除当前内容。
因此,您需要在视图堆栈中的java.awt.Container的每个后代中覆盖update(...)
,但尚未执行此操作,例如:
public void update(Graphics g) {
if (isShowing()) paint(g);
}
此外,似乎AWT或JVM或其他人(尚未想到这一点)也清除了主窗口的背景,与任何Container的更新方法无关。要防止出现这种情况,请按照@ WhiteFang34的建议,将以下行添加到您的代码中:
System.setProperty("sun.awt.noerasebackground", "true");
只做这两件事终于解决了我的闪烁问题......