Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/user-interface/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java AWT画布在手动调整大小时闪烁_Java_User Interface_Swing_Awt - Fatal编程技术网

Java AWT画布在手动调整大小时闪烁

Java AWT画布在手动调整大小时闪烁,java,user-interface,swing,awt,Java,User Interface,Swing,Awt,只是出于智力上的兴趣,你可以使画布在手动调整大小时不闪烁 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 frameWidt

只是出于智力上的兴趣,你可以使画布在手动调整大小时不闪烁

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编辑器中复制粘贴并运行该示例。

我认为关键是使用双缓冲区,一种可能的解决方法是使用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);
   }
}

您可以将其添加到主方法的开头,以避免背景闪烁:

System.setProperty("sun.awt.noerasebackground", "true");

我知道这个问题由来已久,但在我寻找的过程中,我发现了一个解决方案:

有两个问题:

一方面,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或其他任何人(还没有弄清楚这一点)似乎也会清除主窗口的背景,而与任何容器的更新方法无关。为了防止出现这种情况,请按照@WhiteFang34的建议,在代码的某个地方添加以下行:

System.setProperty("sun.awt.noerasebackground", "true");

只有同时完成这两项工作,才能最终解决我的闪烁问题……

“您可以在Java编辑器中复制粘贴并运行示例。”而不是在编译产生25个错误时。为了更快地获得更好的帮助,请发布一条消息。@Andrew:我相信他忘记了导入。@HFOE:+1我有时会明确说明
super(true)
constructor.OP要求纯
java.awt
解决方案。“不摇摆”。他问,他绝对不会考虑使用挥杆吗?事实上,必须把它放在虚拟机的论点中。我刚刚做了另一个我想用它的项目,它使用了
-D
标志。为我完全解决了闪烁问题,但我仍然不明白,为什么我不必重写paint(…)方法,因为它在渲染子对象之前默认也会清除组件。我以为操作系统会直接调用绘画方法,因为系统触发了绘画?