2013-02-23 155 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