【问题标题】:Painted content invisible while resizing in Java在 Java 中调整大小时绘制的内容不可见
【发布时间】:2011-04-02 01:43:46
【问题描述】:

请注意,我没有在 Windows 机器上仅在 Mac 机器上测试过这个。我不太确定这是否也发生在 Windows 机器上...

当我调整我的 Java 应用程序的大小时,内容是不可见的。我已经找到了一种方法来修复它调整它的大小之后,但不是用户正在调整窗口大小。

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

结构是这样的:

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

我已将所有侦听器添加到 My main-window,现在我可以重绘 Content-view 调整窗口大小后.

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

我注意到使用paint(getGraphics())-方法并不是一个很好的方法来做到这一点,但由于repaint()-方法根本不做任何事情,这是唯一可行的可能性。

调整大小时,所有绘制的内容都变得不可见。但是,当我将 Button-instance 添加到我的 Content-view 并调整我的 Main-window 大小时,按钮不会变得不可见。

能够追踪“实时”调整大小事件:

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

当我将我的重绘方法(或官方重绘方法)添加到这样的“实时”调整大小事件中时,我仍然得到输出,但是,它不是重绘之类的

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

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

我没有使用Graphics2D 之类的,只是Graphics

您能解释一下如何重新绘制视图吗?

提前致谢, 蒂姆

【问题讨论】:

  • 另见“在 AWT 和 Swing 中绘画”java.sun.com/products/jfc/tsc/articles/painting/index.html
  • 考虑发布简短的、独立的、正确的(可编译的)示例(SSCCE)来说明问题:sscce.org
  • 我建议调查一下为什么您认为 Swing 使您的应用程序如此缓慢,而不是尝试使用 AWT 组件来解决这个限制。

标签: java graphics resize window minimize


【解决方案1】:

好的,我终于修好了。

您不需要在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 秒左右,但我并不在乎。

【讨论】:

  • 我认为还有更优雅的解决方案:)
【解决方案2】:

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

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);
        }
    }
}
【解决方案3】:

我对 Swing 比较熟悉,但文章 Painting in AWT and Swing 区分了系统触发的绘画和应用程序触发的绘画。下面的示例显示了系统如何在调整窗口大小时调用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);
        }
    }
}
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-09-29
  • 1970-01-01
  • 1970-01-01
  • 2012-08-30
  • 2019-09-11
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多