【问题标题】:Prevent drawing over the same area of a Graphics2D防止在 Graphics2D 的同一区域上绘图
【发布时间】:2013-02-04 19:37:50
【问题描述】:

语言:Java。

您好,我需要防止在 Graphics2D 的同一位置上多次绘制。例如,如果用户在某个区域上使用带圆帽且宽度为 10 的 BasicStroke 进行绘制,则无法再次绘制该区域。

我想这样做的原因是,用户可以在图像上绘制(徒手)半透明颜色,而无需在同一笔划上绘制(从而增加颜色的密度并降低其半透明度)。

我尝试存储用户所做的所有笔划的形状(作为减去形状的 Area 对象),然后通过所有这些 Area 对象的交集来裁剪 Graphics2D。

这几乎可行,但剪辑获得的“形状”与笔划绘制的“形状”并不完全相同 - 相差几个像素。

有没有人有其他可行的想法?

【问题讨论】:

  • 这个问题很适合sscce 分析。请考虑创建其中之一并将其发布在此处。
  • 而不是直接绘制到Graphics2D 上下文,创建一个透明的BufferedImage,绘制笔触,然后使用所需的 alpha 将其绘制回主图形上下文
  • 一种方法是 1) 将原始(未更改的)图像保存在缓存中。 2)将副本添加到标签以进行显示(如果需要,使用鼠标侦听器进行绘图) 3)从用户(Shape)获取他们正在绘制的输入。 4) 将其添加到“元形状” 5) 绘制第一张图像,然后将元形状绘制到第二张图像。

标签: java graphics awt shape clip


【解决方案1】:

这个概念比较简单,你需要有多个可以渲染的层......

有多种不同的方法可以解决问题。您可以维护Points 的列表,并在每个绘制周期中,将这些点渲染到后备缓冲区,然后您将使用AlphaComposite 在主要内容上绘制。

您可以(如本示例那样)直接绘制到后备缓冲区和 repaint 内容,再次使用 AlphaComposite 渲染更高层。

你可以有任意数量的层...

import java.awt.AlphaComposite;
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.geom.Line2D;
import java.awt.image.BufferedImage;
import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.UIManager;

public class PaintOver {

    public static void main(String[] args) {
        new PaintOver();
    }

    public PaintOver() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (Exception ex) {
                }

                JFrame frame = new JFrame("Test");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.add(new MapPane());
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);

            }
        });
    }

    public class MapPane extends JPanel {

        private BufferedImage background;
        private BufferedImage foreground;

        public MapPane() {
            try {
                background = ImageIO.read(getClass().getResource("/TreasureMap.png"));
                foreground = new BufferedImage(background.getWidth(), background.getHeight(), BufferedImage.TYPE_INT_ARGB);
            } catch (Exception e) {
                e.printStackTrace();
            }

            MouseAdapter mouseHandler = new MouseAdapter() {
                private Point startPoint;

                @Override
                public void mousePressed(MouseEvent e) {
                    startPoint = e.getPoint();
                }

                @Override
                public void mouseReleased(MouseEvent e) {
                    startPoint = null;
                }

                @Override
                public void mouseDragged(MouseEvent e) {
                    Point endPoint = e.getPoint();
                    Graphics2D g2d = foreground.createGraphics();

                    Point offset = getOffset();

                    Point from = new Point(startPoint);
                    from.translate(-offset.x, -offset.y);
                    Point to = new Point(endPoint);
                    to.translate(-offset.x, -offset.y);
                    g2d.setColor(Color.RED);
                    g2d.setStroke(new BasicStroke(4, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND));
                    g2d.draw(new Line2D.Float(from, to));
                    g2d.dispose();
                    startPoint = endPoint;
                    repaint();
                }
            };

            addMouseListener(mouseHandler);
            addMouseMotionListener(mouseHandler);

        }

        @Override
        public Dimension getPreferredSize() {
            return background == null ? super.getPreferredSize() : new Dimension(background.getWidth(), background.getHeight());
        }

        protected Point getOffset() {
            Point p = new Point();
            if (background != null) {
                p.x = (getWidth() - background.getWidth()) / 2;
                p.y = (getHeight() - background.getHeight()) / 2;
            }
            return p;
        }

        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            if (background != null) {
                Graphics2D g2d = (Graphics2D) g.create();
                Point offset = getOffset();

                g2d.drawImage(background, offset.x, offset.y, this);
                g2d.setComposite(AlphaComposite.SrcOver.derive(0.5f));
                g2d.drawImage(foreground, offset.x, offset.y, this);
                g2d.dispose();
            }
        }
    }
}

【讨论】:

    猜你喜欢
    • 2014-10-25
    • 2018-12-31
    • 1970-01-01
    • 2018-07-23
    • 1970-01-01
    • 2012-10-29
    • 1970-01-01
    • 1970-01-01
    • 2013-08-21
    相关资源
    最近更新 更多