1

我正在尝试在 Swing/JPanel 中创建一些代码,该代码采用一些(可变)变量并绘制如下图:

图片

我不知道从哪里开始。这个想法是在六边形上会有一个关键点,每个变量一个,每个点之间会画一条线,然后自定义形状内部的空间会被遮蔽。有什么想法吗?

代码原型

import java.awt.*;
import javax.swing.*;

public class DrawPolygon extends JPanel {

int xOffset = 0;
int yOffset = 0;
int sizeModifer = 50;
int numOfPoints = 8;
int linePosition = 80;
double sizeMultiplier = 1;

@Override
public void paintComponent(Graphics g) {
    super.paintComponent(g);

    Polygon[] polygons = new Polygon[5];
    for (int i = 0; i < polygons.length; i++){
        polygons[i] = new Polygon();
        for (int q = 0; q < numOfPoints; q++) {
            polygons[i].addPoint(
                xOffset + (int) (linePosition + (sizeModifer*sizeMultiplier)
                * Math.cos(q * 2 * Math.PI / numOfPoints)),
                yOffset + (int) ((linePosition - 10) + (sizeModifer*sizeMultiplier)
                * Math.sin(q * 2 * Math.PI / numOfPoints)));
        }//built points
        sizeMultiplier = sizeMultiplier - 0.2;
    }//build polygon arrays

    Polygon innerPolygon = new Polygon();
    for (int i = 0; i < numOfPoints; i++) {
        int randomRange = 5 + (int) (Math.random() * ((sizeModifer - 5) + 1));
        innerPolygon.addPoint(
            xOffset + (int) (linePosition + randomRange
            * Math.cos(i * 2 * Math.PI / numOfPoints)),
            yOffset + (int) ((linePosition - 10) + randomRange
            * Math.sin(i * 2 * Math.PI / numOfPoints)));
    }
    Graphics2D g2d = (Graphics2D) g;
    g2d.setRenderingHint(
        RenderingHints.KEY_ANTIALIASING,
        RenderingHints.VALUE_ANTIALIAS_ON);
    g2d.setStroke(new BasicStroke(1));

    for (int i = 0; i < polygons.length; i++){
        g2d.setColor(Color.green);
        g2d.fill(polygons[i]);
        g2d.setColor(Color.black);
        g2d.draw(polygons[i]);
    }//draw polygons from arrays

    double distanceModifier = 1;
    for (int i = 0; i < numOfPoints; i++) {
        g2d.drawString("test"+(i+1),
            xOffset + (int) (linePosition + (sizeModifer*distanceModifier)
            * Math.cos(i * 2 * Math.PI / numOfPoints)),
            yOffset + (int) ((linePosition - 10) + (sizeModifer*distanceModifier)
            * Math.sin(i * 2 * Math.PI / numOfPoints)));
        distanceModifier = distanceModifier +.01;
    }

    g2d.setColor(new Color(255,213,200,90));
    g2d.fill(innerPolygon);
    g2d.setColor(Color.red);
    g2d.draw(innerPolygon);
}

@Override
public Dimension getPreferredSize() {
    // TODO calculate size based on geometry
    return new Dimension(160, 160);
}

public static void main(String[] args) {
    EventQueue.invokeLater(new Runnable() {
        @Override
        public void run() {
            JFrame frame = new JFrame();
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            frame.setTitle("Show Different Polygons");
            frame.add(new DrawPolygon());
            frame.pack();
            frame.setLocationByPlatform(true);
            frame.setVisible(true);
        }
    });
}

}

4

3 回答 3

5

JFreeChart包括一个SpiderWebPlot,在“杂项”下的演示中显示,并在此处 讨论。虽然包含五个类别,但您的图像似乎包含六个。SpiderWebChartDemo1

图片

于 2013-02-24T03:24:22.567 回答
3

当然。我确信已经有 Java 库可以做到这一点。例如,Sonar显示了与此类似的图表。通常最好使用其他人的组件,而不是尽可能编写自己的组件。通常我会使用 JFreeChart,但它看起来没有这样的组件。

如果你想自己写,你只需要对网络上每个点的位置做一些简单的计算。从中心开始,您将首先在 0 度处绘制一条线。然后每条后续的径向线将旋转2*pi/n弧度。您可以应用一些简单的三角函数从每个六边形的角度和半径中计算出笛卡尔 (x, y) 坐标。最后,您将覆盖填充区域。所以算法可能是这样的。在下面的伪代码中,参数values是一个小正整数列表,表示多边形上的每个点,作为距图表中心的偏移量。因此,对于六边形,您将在此列表中有六个值。

function drawGraph(values):

    steps = maximum value from values
    lines = number of values

    webWidth = min(width, height)
    centerX = width / 2
    centerY = height / 2

    // Draw lines

    for radialLineNumber in 0..lines:
        angle = radialLineNumber * 2 * pi / lines;
        draw line from (centerX, centerY) to (centerX + cos(angle)*webWidth, centerY + sin(angle) * webWidth))
        edgePolygon = blank polygon
        for edgeNumber in 1..steps:
            x = centerX + cos(angle) * webWidth * edgeNumber / steps
            y = centerY + sin(angle) * webWidth * edgeNumber / steps
            add (x, y) to edgePolygon
        stroke polygon edgePolygon

    // Draw polygon

    areaPolygon = blank polygon
    radialLineNumber = 0
    for value in values:
        angle = radialLineNumber * 2 * pi / lines;
        x = centerX + cos(angle) * value * webWidth / steps
        y = centerY + sin(angle) * value * webWidth / steps
        add (x, y) to areaPolygon
    fill polygon areaPolygon

我将把这个伪代码翻译成真正的JComponent. 我使用的所有功能都是 onMathGraphics2D. 您可能需要在绘制区域多边形之前设置它的不透明度。

于 2013-02-23T21:04:53.720 回答
2

关于您的示例的一些说明:

  • 使用 的功能Graphics2D来呈现您的Polygon,实现Shape.

  • 覆盖,如这里getPreferredSize()所讨论的。

  • Swing GUI 对象应该事件分派线程上构建和操作。

图片

import java.awt.*;
import javax.swing.*;

public class DrawPolygon extends JPanel {

    int xOffset = 0;
    int yOffset = 0;
    int sizeModifer = 50;
    int numOfPoints = 8;
    int linePosition = 80;

    @Override
    public void paintComponent(Graphics g) {
        super.paintComponent(g);
        Polygon outerPolygon = new Polygon();
        for (int i = 0; i < numOfPoints; i++) {
            outerPolygon.addPoint(
                xOffset + (int) (linePosition + sizeModifer
                * Math.cos(i * 2 * Math.PI / numOfPoints)),
                yOffset + (int) ((linePosition - 10) + sizeModifer
                * Math.sin(i * 2 * Math.PI / numOfPoints)));
        }
        Graphics2D g2d = (Graphics2D) g;
        g2d.setRenderingHint(
            RenderingHints.KEY_ANTIALIASING,
            RenderingHints.VALUE_ANTIALIAS_ON);
        g2d.setColor(Color.cyan);
        g2d.fill(outerPolygon);
        g2d.setStroke(new BasicStroke(2));
        g2d.setColor(Color.red);
        g2d.draw(outerPolygon);
    }

    @Override
    public Dimension getPreferredSize() {
        // TODO calculate size based on geometry
        return new Dimension(160, 160);
    }

    public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                JFrame frame = new JFrame();
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.setTitle("Show Different Polygons");
                frame.add(new DrawPolygon());
                frame.pack();
                frame.setLocationByPlatform(true);
                frame.setVisible(true);
            }
        });
    }
}

附录:根据评论,本次修订恢复了原版innerPolygon

import java.awt.*;
import javax.swing.*;

public class DrawPolygon extends JPanel {

    int xOffset = 0;
    int yOffset = 0;
    int sizeModifer = 50;
    int numOfPoints = 8;
    int linePosition = 80;

    @Override
    public void paintComponent(Graphics g) {
        super.paintComponent(g);
        Polygon outerPolygon = new Polygon();
        for (int i = 0; i < numOfPoints; i++) {
            outerPolygon.addPoint(
                xOffset + (int) (linePosition + sizeModifer
                * Math.cos(i * 2 * Math.PI / numOfPoints)),
                yOffset + (int) ((linePosition - 10) + sizeModifer
                * Math.sin(i * 2 * Math.PI / numOfPoints)));
        }
        Polygon innerPolygon = new Polygon();
        for (int i = 0; i < numOfPoints; i++) {
            int randomRange = 5 + (int) (Math.random() * ((sizeModifer - 5) + 1));
            innerPolygon.addPoint(
                xOffset + (int) (linePosition + randomRange
                * Math.cos(i * 2 * Math.PI / numOfPoints)),
                yOffset + (int) ((linePosition - 10) + randomRange
                * Math.sin(i * 2 * Math.PI / numOfPoints)));
        }
        Graphics2D g2d = (Graphics2D) g;
        g2d.setRenderingHint(
            RenderingHints.KEY_ANTIALIASING,
            RenderingHints.VALUE_ANTIALIAS_ON);
        g2d.setStroke(new BasicStroke(2));
        g2d.setColor(Color.cyan);
        g2d.fill(outerPolygon);
        g2d.setColor(Color.red);
        g2d.draw(outerPolygon);
        g2d.setColor(Color.blue);
        g2d.fill(innerPolygon);
        g2d.setColor(Color.red);
        g2d.draw(innerPolygon);
    }

    @Override
    public Dimension getPreferredSize() {
        // TODO calculate size based on geometry
        return new Dimension(160, 160);
    }

    public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                JFrame frame = new JFrame();
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.setTitle("Show Different Polygons");
                frame.add(new DrawPolygon());
                frame.pack();
                frame.setLocationByPlatform(true);
                frame.setVisible(true);
            }
        });
    }
}
于 2013-02-24T14:55:34.483 回答