在Java中resize时,绘制的内容不可见

请注意,我没有在Mac机上的Windows机器上testing过。 我不确定这是否也发生在Windows机器上…

当我调整我的Java应用程序的内容是不可见的。 我已经find了resize修复它的方法,但不是用户调整窗口大小的时候。

我没有使用Swing或其他东西,因为它使我的二进制文件变得如此缓慢(在我看来)。

结构是这样的:

  • Frame我的主窗口
    • Containe r main-window内容视图
      • 基于Container的子视图,包括paint(Graphics g) – 方法

我已经将所有侦听器添加到“ My main-window ,现在我可以调整窗口大小重新绘制内容视图

 public void componentResized(ComponentEvent e) { this.contentView.paint(this.contentView.getGraphics()); } 

我小心使用paint(getGraphics())方法 – 方法不是一个很好的方法来做到这一点,但由于repaint()方法根本没有做任何事情,这是唯一的工作可能性。

在resize时,所有绘制的内容变得不可见。 但是,当我添加一个Button实例到我的Content-view并调整我的Main-window ,button不会看不见。

我能够追踪“活”resize事件:

 public void componentMoved(ComponentEvent e) { System.out.println("Live-resize"); } 
  1. 当我开始resize这个方法不被调用。
  2. resize时,会在我的日志中生成“实时resize”每一个像素我调整窗口的大小。
  3. 当我停止resize这个方法不被调用,componentResized方法。

当我将重绘方法(或重绘方法)添加到这样的“活”resize事件时,我仍然得到输出,但是,它不是重绘或某事

 public void componentMoved(ComponentEvent e) { System.out.println("Live-resize"); this.contentView.paint(this.contentView.getGraphics()); } 

要么

 public void componentMoved(ComponentEvent e) { System.out.println("Live-resize"); this.contentView.repaint(); } 

当我最小化我的应用程序到docker,并再次最大化应用程序时,同样的事情发生,我想,相同的代码是需要解决这个问题。

我没有使用Graphics2D或什么的,只是Graphics

你能解释一下我怎么重画这些意见?

提前感谢蒂姆

作为参考,这里是使用Swing的相同程序。 因为JPanel是双缓冲的,所以在resize后释放鼠标不会闪烁。

 import java.awt.*; import java.awt.event.*; import java.util.Random; import javax.swing.*; public class SwingPaint { public static void main(String[] args) { JFrame frame = new JFrame(); frame.add(new CirclePanel()); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.pack(); frame.setVisible(true); } private static class CirclePanel extends JPanel { private static final Random r = new Random(); public CirclePanel() { this.setPreferredSize(new Dimension(320, 240)); this.setForeground(new Color(r.nextInt())); this.addMouseListener(new MouseAdapter() { @Override public void mousePressed(MouseEvent e) { CirclePanel.this.update(); } }); } public void update() { this.setForeground(new Color(r.nextInt())); } @Override public void paintComponent(Graphics g) { super.paintComponent(g); Dimension size = this.getSize(); int d = Math.min(size.width, size.height) - 10; int x = (size.width - d) / 2; int y = (size.height - d) / 2; g.fillOval(x, y, d, d); g.setColor(Color.blue); g.drawOval(x, y, d, d); } } } 

我对Swing更加熟悉,但AWT和Swing中的“ Painting”一词区分了系统和应用程序触发的绘画。 下面的例子显示了当窗口resize时系统调用paint()的方式,而应用程序调用repaint()来调用update() ,以响应鼠标事件。 行为是跨平台的。

 import java.awt.*; import java.awt.event.*; import java.util.Random; public class AWTPaint { public static void main(String[] args) { Frame frame = new Frame(); frame.add(new CirclePanel()); frame.addWindowListener(new WindowAdapter() { @Override public void windowClosing(WindowEvent e) { System.exit(0); } }); frame.pack(); frame.setVisible(true); } private static class CirclePanel extends Panel { private static final Random r = new Random(); public CirclePanel() { this.setPreferredSize(new Dimension(320, 240)); this.setForeground(new Color(r.nextInt())); this.addMouseListener(new MouseAdapter() { @Override public void mousePressed(MouseEvent e) { CirclePanel.this.repaint(); } }); } @Override public void update(Graphics g) { this.setForeground(new Color(r.nextInt())); } @Override public void paint(Graphics g) { Dimension size = this.getSize(); int d = Math.min(size.width, size.height) - 10; int x = (size.width - d) / 2; int y = (size.height - d) / 2; g.fillOval(x, y, d, d); g.setColor(Color.blue); g.drawOval(x, y, d, d); } } } 

好的,我终于修好了。

而不是每次在paint(Graphics g)方法中重绘它,你需要缓冲输出,只重绘这个图像(我有点希望Java已经这样做了,就像Obj-C一样)。

 public BufferedImage buffer; public void redraw() { buffer = new BufferedImage( 200, // height 300, // width BufferedImage.TYPE_4BYTE_ABGR); // ABGR = RGBA, 4-byte (r, g, b, a) per pixel Graphics g = buffer.getGraphics(); // do your drawing here if (this.getGraphics()) { // 'this' is already shown, so it needs a redraw this.paint(this.getGraphics()); // little hack } } public void update(Graphics g) { this.paint(g); } public void paint(Graphics g) { g.drawImage(buffer, 0, 0, this); } 

现在,当你最小化窗口并再次最大化时,绘画依然存在。 只是,窗户现在闪烁了0.1秒左右,但我并不在乎。