【问题标题】:Paint component for panel doesn't draw double point values面板的油漆组件不绘制双点值
【发布时间】:2018-11-23 08:48:07
【问题描述】:

我有一些坐标点,我试图绘制相对于彼此的坐标点,但无法显示这些点。我正在使用的。这些点不起作用:

double[][] subjPoints = {{38.81904602050781,-71.00624084472656}, 
{38.81904602050781,-70.29379272460938}, {37.95466232299805,-
70.35797882080078}, {37.9495735168457,-71.03191375732422}};

double[][] clipPoints = {{38.62575820040764,-70.84753473092672}, {38.418853759765625,-71.02689361572266},
{38.21194931912361,-71.2057395294625}, {37.931301169971185,-70.67791159484983},
{38.1382056106132,-70.49975311140243}, {38.34511005125521,-70.32108875708619}};

这些点确实有效:

double[][] subjPoints = {{50, 150}, {200, 50}, {350, 150}, {350, 300},
    {250, 300}, {200, 250}, {150, 350}, {100, 250}, {100, 200}};

double[][] clipPoints = {{100, 100}, {300, 100}, {300, 300}, {100, 300}};

_

@Override
public void paintComponent(Graphics g) {
    super.paintComponent(g);
    Graphics2D g2 = (Graphics2D) g;
    g2.translate(30, 60);
    g2.setStroke(new BasicStroke(3));
    g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
            RenderingHints.VALUE_ANTIALIAS_ON);


    drawPolygon(g2, subjPoints, Color.blue);
    drawPolygon(g2, clipPoints, Color.red);


}

private void drawPolygon(Graphics2D g2, List<PointA> points, Color color) {
    g2.setColor(color);
    int len = points.size();
    Line2D line = new Line2D.Double();
    for (int i = 0; i < len; i++) {
        PointA p1 = points.get(i);
        PointA p2 = points.get((i + 1) % len);
        line.setLine(p1.getX(), p1.getY(), 
                p2.getX(), p2.getY());
        g2.draw(line);
    }
}

【问题讨论】:

  • 一眼看去,所有的 y 值似乎都是负数(小于 -70)。您是否尝试过不使用g2.translate(30, 60);,而是使用g2.translate(30, 60+70); 之类的...?
  • 谢谢,这有助于将它带入框架,但由于这些点非常靠近,它只显示为一个小点。有什么办法可以放大吗?
  • 您也可以使用g.scale(10,10) 将所有内容缩放 10 倍,但请注意,当您进行 多个 转换(如平移和缩放)时,它可能变为巧妙地让他们的订单正确。您还可以考虑直接在输入中转换点,例如计算它们的边界框并将其缩放以填充屏幕。无耻的自我推销:对于交互式平移和缩放,您可以考虑我的github.com/javagl/Viewer/tree/master/viewer-core库。
  • 我应该如何让它显示得更大,同时还能看到它。似乎如果我缩放它以使其更大,它最终会超出框架并且什么都没有显示。

标签: java graphics double coordinates draw


【解决方案1】:

您有一组 2D 点,并希望将它们绘制成 JPanel。目标是确保点集在面板中“正确”呈现。在这里我假设“正确”意味着所有的点都应该是可见的,并且应该被渲染,以便它们基本上填满可用的空间。

对此有不同的方法。

最基本的方法将涉及以下步骤(暂时忽略一些实现细节):

  • 你必须计算点的边界框
  • 您必须计算必须应用于点的变换,以便它们填满屏幕。这个变换可以从边界框计算出来
  • 你必须变换点
  • 您必须绘制转换后的点

在下面的示例代码中,这些步骤在ScaledPaintingPlainPanel 类的convertToPointscomputeBoundingBoxcomputeTransformtransformPointsdrawPolygon 方法中实现。

在您的情况下,这些点实际上是 多边形 的点 - 也就是说,它们与线相连。这可以使事情变得更简单:您可以将点转换为java.awt.Shape,这样您就不必手动计算边界框。形状也可以更容易地转换和绘制。这显示在 ScaledPaintingPlainPanelSimpler 类中。

两种情况的结果都是一样的:

代码在这里:

import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridLayout;
import java.awt.RenderingHints;
import java.awt.Shape;
import java.awt.geom.AffineTransform;
import java.awt.geom.Line2D;
import java.awt.geom.Path2D;
import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;
import java.util.ArrayList;
import java.util.List;

import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;

public class ScaledPaintingPlain
{
    public static void main(String[] args)
    {
        SwingUtilities.invokeLater(() -> createAndShowGui());
    }

    private static void createAndShowGui()
    {
        JFrame f = new JFrame();
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        f.getContentPane().setLayout(new GridLayout(1,2));

        ScaledPaintingPlainPanel p0 = 
            new ScaledPaintingPlainPanel();
        f.getContentPane().add(p0);

        ScaledPaintingPlainPanelSimpler p1 = 
            new ScaledPaintingPlainPanelSimpler();
        f.getContentPane().add(p1);

        f.setSize(1200, 800);
        f.setLocationRelativeTo(null);
        f.setVisible(true);
    }
}

class ScaledPaintingPlainPanel extends JPanel
{
    double[][] subjPoints =
    {
        { 38.81904602050781, -71.00624084472656 },
        { 38.81904602050781, -70.29379272460938 },
        { 37.95466232299805, -70.35797882080078 },
        { 37.9495735168457, -71.03191375732422 } 
    };

    double[][] clipPoints =
    {
        { 38.62575820040764, -70.84753473092672 },
        { 38.418853759765625, -71.02689361572266 },
        { 38.21194931912361, -71.2057395294625 },
        { 37.931301169971185, -70.67791159484983 },
        { 38.1382056106132, -70.49975311140243 },
        { 38.34511005125521, -70.32108875708619 } 
    };

    @Override
    public void paintComponent(Graphics g)
    {
        super.paintComponent(g);
        Graphics2D g2 = (Graphics2D) g;
        g2.setStroke(new BasicStroke(3));
        g2.setRenderingHint(
            RenderingHints.KEY_ANTIALIASING,
            RenderingHints.VALUE_ANTIALIAS_ON);

        // Convert the arrays into lists of points
        List<Point2D> sPoints = convertToPoints(subjPoints);
        List<Point2D> cPoints = convertToPoints(clipPoints);

        // Compute the bounding boxes of the point lists
        Rectangle2D sBounds = computeBoundingBox(sPoints);
        Rectangle2D cBounds = computeBoundingBox(cPoints);
        Rectangle2D bounds = new Rectangle2D.Double();
        Rectangle2D.union(sBounds, cBounds, bounds);

        AffineTransform affineTransform = computeTransform(bounds);

        // Transform the points
        transformPoints(sPoints, affineTransform);
        transformPoints(cPoints, affineTransform);

        // Draw the point lists as polygons
        drawPolygon(g2, sPoints, Color.BLUE);
        drawPolygon(g2, cPoints, Color.RED);
    }


    private static List<Point2D> convertToPoints(double array[][])
    {
        List<Point2D> points = new ArrayList<Point2D>();
        for (double a[] : array)
        {
            points.add(new Point2D.Double(a[0], a[1]));
        }
        return points;
    }

    private static Rectangle2D computeBoundingBox(
        Iterable<? extends Point2D> points)
    {
        double minX = Double.MAX_VALUE;
        double minY = Double.MAX_VALUE;
        double maxX = -Double.MAX_VALUE;
        double maxY = -Double.MAX_VALUE;
        for (Point2D p : points)
        {
            minX = Math.min(minX, p.getX());
            minY = Math.min(minY, p.getY());
            maxX = Math.max(maxX, p.getX());
            maxY = Math.max(maxY, p.getY());
        }
        return new Rectangle2D.Double(minX, minY, maxX - minX,  maxY - minY);
    }

    private AffineTransform computeTransform(Rectangle2D bounds)
    {
        // Compute the scaling factor that has to be applied to the
        // points so that the painting fills the screen
        double scaleX = getWidth() / bounds.getWidth();
        double scaleY = getHeight() / bounds.getHeight();
        double scale = Math.min(scaleX, scaleY);

        // Compute the transform that has to be applied to the
        // points so that they fill the screen
        AffineTransform affineTransform = new AffineTransform();
        affineTransform.scale(scale, scale);
        affineTransform.translate(-bounds.getX(), -bounds.getY());

        return affineTransform;
    }

    private static void transformPoints(
        Iterable<? extends Point2D> points, AffineTransform affineTransform)
    {
        for (Point2D point : points)
        {
            affineTransform.transform(point, point);
        }
    }


    private void drawPolygon(Graphics2D g2, List<Point2D> points, Color color)
    {
        g2.setColor(color);
        int len = points.size();
        Line2D line = new Line2D.Double();
        for (int i = 0; i < len; i++)
        {
            Point2D p1 = points.get(i);
            Point2D p2 = points.get((i + 1) % len);
            line.setLine(p1.getX(), p1.getY(), p2.getX(), p2.getY());
            g2.draw(line);
        }
    }
}



class ScaledPaintingPlainPanelSimpler extends JPanel
{
    double[][] subjPoints =
    {
        { 38.81904602050781, -71.00624084472656 },
        { 38.81904602050781, -70.29379272460938 },
        { 37.95466232299805, -70.35797882080078 },
        { 37.9495735168457, -71.03191375732422 } 
    };

    double[][] clipPoints =
    {
        { 38.62575820040764, -70.84753473092672 },
        { 38.418853759765625, -71.02689361572266 },
        { 38.21194931912361, -71.2057395294625 },
        { 37.931301169971185, -70.67791159484983 },
        { 38.1382056106132, -70.49975311140243 },
        { 38.34511005125521, -70.32108875708619 } 
    };

    @Override
    public void paintComponent(Graphics g)
    {
        super.paintComponent(g);
        Graphics2D g2 = (Graphics2D) g;
        g2.setStroke(new BasicStroke(3));
        g2.setRenderingHint(
            RenderingHints.KEY_ANTIALIASING,
            RenderingHints.VALUE_ANTIALIAS_ON);

        // Convert the arrays into shapes
        Shape sShape = convertToShape(subjPoints);
        Shape cShape = convertToShape(clipPoints);

        // Compute the bounding boxes of the shapes
        Rectangle2D sBounds = sShape.getBounds2D();
        Rectangle2D cBounds = cShape.getBounds2D();
        Rectangle2D bounds = new Rectangle2D.Double();
        Rectangle2D.union(sBounds, cBounds, bounds);

        AffineTransform affineTransform = computeTransform(bounds);

        g2.setColor(Color.BLUE);
        g2.draw(affineTransform.createTransformedShape(sShape));
        g2.setColor(Color.RED);
        g2.draw(affineTransform.createTransformedShape(cShape));
    }

    private static Shape convertToShape(double array[][])
    {
        Path2D path = new Path2D.Double();
        for (int i=0; i<array.length; i++)
        {
            double a[] = array[i];
            double x = a[0];
            double y = a[1];
            if (i == 0)
            {
                path.moveTo(x, y);
            }
            else
            {
                path.lineTo(x, y);
            }
        }
        path.closePath();
        return path;
    }

    private AffineTransform computeTransform(Rectangle2D bounds)
    {
        // Compute the scaling factor that has to be applied to the
        // points so that the painting fills the screen
        double scaleX = getWidth() / bounds.getWidth();
        double scaleY = getHeight() / bounds.getHeight();
        double scale = Math.min(scaleX, scaleY);

        // Compute the transform that has to be applied to the
        // points so that they fill the screen
        AffineTransform affineTransform = new AffineTransform();
        affineTransform.scale(scale, scale);
        affineTransform.translate(-bounds.getX(), -bounds.getY());

        return affineTransform;
    }
}

为了完整起见:这是一个类似的例子,使用我的Viewer library

在这种情况下,您还可以使用鼠标平移和缩放渲染的表示。

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.Shape;
import java.awt.geom.AffineTransform;
import java.awt.geom.Path2D;
import java.awt.geom.Rectangle2D;

import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.SwingUtilities;

import de.javagl.viewer.Painter;
import de.javagl.viewer.Viewer;

public class ScaledPaintingViewer
{
    public static void main(String[] args)
    {
        SwingUtilities.invokeLater(() -> createAndShowGUI());
    }

    private static void createAndShowGUI()
    {
        JFrame f = new JFrame("Viewer");
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        f.getContentPane().setLayout(new BorderLayout());

        f.getContentPane().add(
            new JLabel("<html>"
                + "Right mouse drags: Translate<br> "
                + "Left mouse drags: Rotate<br>"
                + "Mouse wheel: Zoom uniformly<br>"
                + "&nbsp;&nbsp;&nbsp;&nbsp; +shift: zoom along x<br>"
                + "&nbsp;&nbsp;&nbsp;&nbsp; +ctrl: zoom along y<br>"
                + "</html>"),
            BorderLayout.NORTH);

        Viewer viewer = new Viewer();
        ScaledPaintingPainter painter = new ScaledPaintingPainter();
        viewer.addPainter(painter);
        viewer.setDisplayedWorldArea(painter.computeBounds());
        f.getContentPane().add(viewer, BorderLayout.CENTER);

        f.setSize(800,800);
        f.setLocationRelativeTo(null);
        f.setVisible(true);
    }
}

class ScaledPaintingPainter implements Painter
{
    double[][] subjPoints =
    {
        { 38.81904602050781, -71.00624084472656 },
        { 38.81904602050781, -70.29379272460938 },
        { 37.95466232299805, -70.35797882080078 },
        { 37.9495735168457, -71.03191375732422 } 
    };

    double[][] clipPoints =
    {
        { 38.62575820040764, -70.84753473092672 },
        { 38.418853759765625, -71.02689361572266 },
        { 38.21194931912361, -71.2057395294625 },
        { 37.931301169971185, -70.67791159484983 },
        { 38.1382056106132, -70.49975311140243 },
        { 38.34511005125521, -70.32108875708619 } 
    };

    @Override
    public void paint(
        Graphics2D g, AffineTransform worldToScreen, double w, double h)
    {
        // Convert the arrays into shapes
        Shape sShape = convertToShape(subjPoints);
        Shape cShape = convertToShape(clipPoints);

        g.setColor(Color.BLUE);
        g.draw(worldToScreen.createTransformedShape(sShape));
        g.setColor(Color.RED);
        g.draw(worldToScreen.createTransformedShape(cShape));
    }

    Rectangle2D computeBounds()
    {
        // Convert the arrays into shapes
        Shape sShape = convertToShape(subjPoints);
        Shape cShape = convertToShape(clipPoints);

        // Compute the bounding boxes of the shapes
        Rectangle2D sBounds = sShape.getBounds2D();
        Rectangle2D cBounds = cShape.getBounds2D();
        Rectangle2D bounds = new Rectangle2D.Double();
        Rectangle2D.union(sBounds, cBounds, bounds);

        return bounds;
    }

    private static Shape convertToShape(double array[][])
    {
        Path2D path = new Path2D.Double();
        for (int i=0; i<array.length; i++)
        {
            double a[] = array[i];
            double x = a[0];
            double y = a[1];
            if (i == 0)
            {
                path.moveTo(x, y);
            }
            else
            {
                path.lineTo(x, y);
            }
        }
        path.closePath();
        return path;
    }

}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-02-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-11-01
    • 2013-06-05
    相关资源
    最近更新 更多