首页 > 解决方案 > 检查矩形是否与文本相交

问题描述

我有一个名为“MapObject”的类,它允许您定义它是什么,它做什么。我最近在其中添加了文本,它工作正常,但是碰撞是一个矩形,在某些情况下并不可怕,但是我希望有一个与文本匹配的碰撞框(也就是检查 1x1 矩形是否与文本,但仍然可以在字母之间)

我尝试了以下方法:

GlyphVector vec = ob.font.createGlyphVector(new Canvas().getFontMetrics(ob.font).getFontRenderContext(), ob.text);
Shape textSh = vec.getOutline();
Area obSh = new Area(new Rectangle(x,y,o.width,o.height));
obSh.intersect(new Area(textSh));
boolean inter = !obSh.isEmpty();

但是它不起作用,我想是因为位置,但是我不知道如何在其中添加位置。谢谢。

标签: javatextawtjava-2d

解决方案


您可能需要做的一件事是将 theGlyphVectorRectangle转换为正确的上下文。

我的意思是,GlyphVectoronly 表示原点处的0x0文本,所以如果文本显示在屏幕上的其他位置,那么你没有得到正确的表示。

幸运的是,有人真正考虑过这个用例并提供了一些功能来做到这一点。有关GlyphVector#getOutline(float, float)更多详细信息,请参阅。

然后你可以使用它......

import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.Shape;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.font.FontRenderContext;
import java.awt.font.GlyphVector;
import java.awt.geom.Rectangle2D;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Random;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.Timer;

public class Test {

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

    public Test() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                JFrame frame = new JFrame();
                frame.add(new TestPane());
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public class TestPane extends JPanel {

        private List<Rectangle> boxes;
        private Map<Rectangle, Point> vectors;

        public TestPane() {
            boxes = new ArrayList<>(25);
            vectors = new HashMap<>(25);
            Random random = new Random();
            for (int index = 0; index < 10; index++) {
                int x = random.nextInt(400 - 10);
                int y = random.nextInt(400 - 10);

                Rectangle box = new Rectangle(x, y, 10, 10);
                boxes.add(box);

                int xDelta = random.nextBoolean() ? 1 : -1;
                int yDelta = random.nextBoolean() ? 1 : -1;

                vectors.put(box, new Point(xDelta, yDelta));
            }

            Timer timer = new Timer(40, new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    for (Rectangle box : boxes) {
                        Point delta = vectors.get(box);

                        if (delta == null) {
                            int xDelta = random.nextBoolean() ? 1 : -1;
                            int yDelta = random.nextBoolean() ? 1 : -1;
                            delta = new Point(xDelta, yDelta);
                        }

                        int x = box.x + delta.x;
                        int y = box.y + delta.y;

                        if (x < 0) {
                            x = 0;
                            delta.x *= -1;
                        } else if (x + box.width > getWidth()) {
                            x = getWidth() - box.width;
                            delta.x *= -1;
                        }
                        if (y < 0) {
                            y = 0;
                            delta.y *= -1;
                        } else if (y + box.height > getHeight()) {
                            y = getHeight() - box.height;
                            delta.y *= -1;
                        }

                        box.setLocation(x, y);
                        vectors.put(box, delta);
                    }
                    repaint();
                }
            });
            timer.start();
        }

        @Override
        public Dimension getPreferredSize() {
            return new Dimension(400, 200);
        }

        protected Shape getTextShape() {
            Graphics2D g2d = (Graphics2D) getGraphics();
            if (g2d == null) {
                return null;
            }
            Font font = new Font("Arial", Font.BOLD, 48);
            g2d.setFont(font);

            FontRenderContext frc = g2d.getFontRenderContext();
            GlyphVector gv = font.createGlyphVector(frc, "Cats with hats");
            Rectangle2D box = gv.getVisualBounds();

            // Calclate the location of the text and offset the glyph shape...
            float x = (float) (getWidth() - box.getWidth()) / 2f;
            float y = (float) (((getHeight() - box.getHeight()) / 2f) + (-box.getY()));

            return gv.getOutline(x, y);
        }

        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            Graphics2D g2d = (Graphics2D) g.create();

            Shape shape = getTextShape();

            g2d.setColor(Color.BLACK);
            g2d.fill(shape);
            g2d.setColor(Color.RED);
            g2d.draw(shape);

            for (Rectangle box : boxes) {
                g2d.setColor(Color.BLACK);
                if (shape.intersects(box)) {
                    g2d.setColor(Color.RED);
                }
                g2d.draw(box);
            }
        }

    }

}

推荐阅读