在Java中resize时,绘制的内容不可见
请注意,我没有在Mac机上的Windows机器上testing过。 我不确定这是否也发生在Windows机器上…
当我调整我的Java应用程序的内容是不可见的。 我已经find了resize后修复它的方法,但不是在用户调整窗口大小的时候。
我没有使用Swing或其他东西,因为它使我的二进制文件变得如此缓慢(在我看来)。
结构是这样的:
-
Frame
我的主窗口 -
-
Containe
rmain-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"); }
- 当我开始resize这个方法不被调用。
- resize时,会在我的日志中生成“实时resize”每一个像素我调整窗口的大小。
- 当我停止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秒左右,但我并不在乎。