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

发布于 2024-10-27 06:03:28 字数 1614 浏览 1 评论 0原文

出于智力兴趣,您可以使画布在手动调整大小时不闪烁。

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

Just out of intellectual interest can you make a Canvas not flicker when doing a manual resize.

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);
}
}

You can copy paste in a Java editor and run the example.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

毁我热情 2024-11-03 06:03:28

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

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

You can add this to the beginning of your main method to avoid the background flicker:

System.setProperty("sun.awt.noerasebackground", "true");
∞觅青森が 2024-11-03 06:03:28

我知道这个问题很古老,但在我的搜索过程中出现了,同时我找到了解决方案:

有两个问题:

一方面,java.awt的 update(...) 方法.Container 如下所示:

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");

仅执行这两件事最终解决了我的闪烁问题...

I know this question is ancient, but it came up during my search and I meanwhile found a solution:

There are two problems:

On the one hand, the update(...) method of java.awt.Container looks like the following:

public void update(Graphics g) {
    if (isShowing()) {
        if (! (peer instanceof LightweightPeer)) {
            g.clearRect(0, 0, width, height);
        }
        paint(g);
    }
}

I.e. it calls g.clearRect(...) to erase the current content before painting its children.

Therefore, you need to override update(...) in every descendant of java.awt.Container in your view-stack, that doesn't already do so, with something like:

public void update(Graphics g) {
    if (isShowing()) paint(g);
}

Also, it seems that AWT or the JVM or whoever (haven't figured this out yet) also clears the background of the main window, independent of any Container's update-methods. To prevent this, follow @WhiteFang34's suggestion and add the following line to your code somewhere:

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

Only doing both of these things finally solved my flicker issues...

小耗子 2024-11-03 06:03:28

我认为关键是使用双缓冲,解决这个问题的一种方法是使用默认双缓冲的 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);
   }
}

The key I believe is to use double buffering, and one way to possibly solve this is to use Swing which double buffers by default:

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);
   }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文