2013-02-23 180 views
1

我试图创建的Swing /一些代码的JPanel,需要一些(多变)的变量,并绘制这样的图表:绘制矢量图形7

image

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

代码原型

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

}

+2

假设您掌握了自定义绘画,请从[2D图形](http://docs.oracle.com/javase/tutorial/2d/index.html)开始,否则从[自定义拼接]开始, (http://docs.oracle.com/javase/tutorial/uiswing/painting/) – MadProgrammer 2013-02-23 20:52:05

+0

+1 [sscce](http://sscce.org/)。 – trashgod 2013-02-24 14:55:58

回答

3

肯定。我确定必须有Java库已经这样做;例如,Sonar显示与此类似的图表。通常最好使用别人的组件,而不是在可能的情况下编写自己的组件。通常我会使用JFreeChart,但它看起来像没有这样的组件。

如果你想写自己的,你只需要做一些简单的计算,在网络上的每个点将是。从中心开始,你可以在0度处画一条线。然后每个后续的径向线将被旋转2*pi/n弧度。你可以应用一些简单的三角函数来根据每个六边形的角度和半径计算出Cartesian(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。我使用的所有功能都在MathGraphics2D。在绘制区域之前,您可能需要设置区域多边形的不透明度。

+0

确定您的psydo代码和一些谷歌fu我想出了一些东西,但我似乎无法画出内部多边形,现在我使用随机数来产生内部,但不产生任何第二聚去 – NekoLLX 2013-02-24 05:19:23

+0

@EricG :我详细阐述了这里提出的实现(这里是http://stackoverflow.com/a/15052943/230513)。作为参考,可以看到['SpiderWebPlot'](http://www.jfree.org/jfreechart/api/javadoc/org/jfree/chart/plot/SpiderWebPlot.html)源代码[here](http:// www.jfree.org/jfreechart/api/javadoc/src-html/org/jfree/chart/plot/SpiderWebPlot.html)。 – trashgod 2013-02-24 15:00:55

+0

@trashgod酷,感谢您花时间做到这一点! – 2013-02-25 15:48:22

2

上你的榜样的几个注意事项:

  • 使用Graphics2D功能来渲染Polygon,它实现Shape

  • 替代getPreferredSize(),如讨论here

  • Swing GUI对象应该在event dispatch thread上构建和操纵只有

image

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); 
      } 
     }); 
    } 
} 
+0

优化的代码总是受欢迎的,但是看看你的修改我并没有真正看到任何不熟悉的东西,事实上它看起来像你删除了一些代码,特别是第二个多边形创建,这就是为什么我的真正问题在于,我似乎无法建立一个多边形insde主要代表阴影区域由gfx定型。阴影多边形不是我的问题,它是阴影多边形里面的另一个多边形,让我难住。 – NekoLLX 2013-02-24 20:36:49

+0

啊,我明白了; ['SpiderWebPlot'](http://www.jfree.org/jfreechart/api/javadoc/src-html/org/jfree/chart/plot/SpiderWebPlot.html)使用'setComposite()'获得半透明效果。 – trashgod 2013-02-24 23:36:54

+0

这确实奇迹! 现在我已经在原型中创建了“Rims”,将除了随机框以外的所有东西都放入了一系列pologon中,但是不知何故,它们会将它们全部打开,如何? (请参阅编辑主题) – NekoLLX 2013-02-25 03:53:36