2012-07-30 80 views
6

我想知道如何在JavaFX中繪製半圓。我嘗試使用Shape和QuadCurve,但我無法制作完美的半圓。繪製半環 - JavaFX

這裏是什麼,我想畫一幅畫:

enter image description here

回答

10

您鏈接的圖片實際上是一個半環。您可以通過繪製嵌套的2個弧和一些線在JavaFX中獲得它。但我最喜歡的方式是使用Path

public class SemiDemo extends Application { 

    @Override 
    public void start(Stage primaryStage) { 

     Group root = new Group(); 
     root.getChildren().add(drawSemiRing(120, 120, 100, 50, Color.LIGHTGREEN, Color.DARKGREEN)); 
     root.getChildren().add(drawSemiRing(350, 350, 200, 30, Color.LIGHTSKYBLUE, Color.DARKBLUE)); 

     Scene scene = new Scene(root, 300, 250); 
     primaryStage.setScene(scene); 
     primaryStage.show(); 
    } 

    private Path drawSemiRing(double centerX, double centerY, double radius, double innerRadius, Color bgColor, Color strkColor) { 
     Path path = new Path(); 
     path.setFill(bgColor); 
     path.setStroke(strkColor); 
     path.setFillRule(FillRule.EVEN_ODD); 

     MoveTo moveTo = new MoveTo(); 
     moveTo.setX(centerX + innerRadius); 
     moveTo.setY(centerY); 

     ArcTo arcToInner = new ArcTo(); 
     arcToInner.setX(centerX - innerRadius); 
     arcToInner.setY(centerY); 
     arcToInner.setRadiusX(innerRadius); 
     arcToInner.setRadiusY(innerRadius); 

     MoveTo moveTo2 = new MoveTo(); 
     moveTo2.setX(centerX + innerRadius); 
     moveTo2.setY(centerY); 

     HLineTo hLineToRightLeg = new HLineTo(); 
     hLineToRightLeg.setX(centerX + radius); 

     ArcTo arcTo = new ArcTo(); 
     arcTo.setX(centerX - radius); 
     arcTo.setY(centerY); 
     arcTo.setRadiusX(radius); 
     arcTo.setRadiusY(radius); 

     HLineTo hLineToLeftLeg = new HLineTo(); 
     hLineToLeftLeg.setX(centerX - innerRadius); 

     path.getElements().add(moveTo); 
     path.getElements().add(arcToInner); 
     path.getElements().add(moveTo2); 
     path.getElements().add(hLineToRightLeg); 
     path.getElements().add(arcTo); 
     path.getElements().add(hLineToLeftLeg); 

     return path; 
    } 

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

有關代碼中使用的形狀的更多信息,請參閱JavaFX的Shape API
截圖:

enter image description here

+0

年,完美! :D這正是我需要的^^非常感謝! – AwaX 2012-07-30 12:14:35

+0

您是否知道是否有簡單的方法來修改路徑的旋轉點? – AwaX 2012-07-31 11:59:51

+0

@AwaX path.setRotate(45); – 2012-07-31 12:26:05

4

建議:

  • 如果你並不需要一個完整的大綱路徑,你可以只使用一個弧。
  • 如果您不需要填充的圓弧並且只想跟蹤圓弧的輪廓路徑,則將圓弧的填充設置爲空。
  • 如果您想讓粗線的粗線路徑較粗,則在弧上設置筆觸參數。
  • 如果你需要一個粗略的圓弧,那麼最好定義一個完整的圓弧,就像Uluk的答案一樣。

示例代碼:

import javafx.application.Application; 
import javafx.scene.*; 
import javafx.scene.paint.Color; 
import javafx.scene.shape.*; 
import javafx.stage.Stage; 

public class SemiCircleSample extends Application { 
    @Override public void start(Stage stage) { 
    Arc arc = new Arc(50, 50, 25, 25, 0, 180); 
    arc.setType(ArcType.OPEN); 
    arc.setStrokeWidth(10); 
    arc.setStroke(Color.CORAL); 
    arc.setStrokeType(StrokeType.INSIDE); 
    arc.setFill(null); 

    stage.setScene(new Scene(new Group(arc), 100, 80)); 
    stage.show(); 
    } 

    public static void main(String[] args) { launch(args); } 
} 
+0

謝謝你,但它是一個完整的半圓,我想繪製的是一個空心的半圓。我在之前的文章中包含了一個示例,顯示了我正在嘗試繪製的內容。 – AwaX 2012-07-30 11:39:27

+0

已更新答案,以演示繪製具有指定筆畫和無填充(將生成半環圖像)的弧線。 – jewelsea 2012-07-30 17:10:18

+0

非常感謝你的更新,你的解決方案更方便,但你不能像你說的那樣填滿弧線,所以我想我會採取其他解決方案。 – AwaX 2012-07-31 11:57:10

0

Path.arcTo()的參數SweepAngle指旋轉的程度,如果是sweepAngle正弧是順時針,如果sweepAngle是負弧是逆時針方向。

該代碼在我的生產環境中使用,它繪製使用位圖圖像半圓形環,路徑變爲順時針上的外半徑,和內半徑逆時針:

drawpercent = 0.85; //this draws a semi ring to 85% you can change it using your code. 
DegreesStart = -90; 
DegreesRotation = 180; 

radiusPathRectF = new android.graphics.RectF((float)CentreX - (float)Radius, (float)CentreY - (float)Radius, (float)CentreX + (float)Radius, (float)CentreY + (float)Radius); 
innerradiusPathRectF = new android.graphics.RectF((float)CentreX - (float)InnerRadius, (float)CentreY - (float)InnerRadius, (float)CentreX + (float)InnerRadius, (float)CentreY + (float)InnerRadius); 

Path p = new Path(); //TODO put this outside your draw() function, you should never have a "new" keyword inside a fast loop. 

       degrees = (360 + (DegreesStart)) % 360; 
       radians = (360 - degrees + 90) * Math.PI/180.0; 
       //radians = Math.toRadians(DegreesStart); 
       int XstartOuter = (int)Math.round((Math.cos(radians) * Radius + CentreX)); 
       int YstartOuter = (int)Math.round((Math.sin(-radians)* Radius + CentreY)); 
       int XstartInner = (int)Math.round((Math.cos(radians) * InnerRadius + CentreX)); 
       int YstartInner = (int)Math.round((Math.sin(-radians) * InnerRadius + CentreY)); 

       degrees = (360 + (DegreesStart + drawpercent * DegreesRotation)) % 360; 
       //radians = degrees * Math.PI/180.0; 
       radians = (360 - degrees + 90) * Math.PI/180.0; 
       //radians = Math.toRadians(DegreesStart + drawpercent * DegreesRotation); 
       int XendOuter = (int)Math.round((Math.cos(radians) * Radius + CentreX)); 
       int YendOuter = (int)Math.round((Math.sin(-radians) * Radius + CentreY)); 
       int XendInner = (int)Math.round((Math.cos(radians) * InnerRadius + CentreX)); 
       int YendInner = (int)Math.round((Math.sin(-radians) * InnerRadius + CentreY)); 

       //draw a path outlining the semi-circle ring. 
       p.moveTo(XstartInner, YstartInner); 
       p.lineTo(XstartOuter, YstartOuter); 
       p.arcTo(radiusPathRectF, (float)DegreesStart - (float)90, (float)drawpercent * (float)DegreesRotation); 
       p.lineTo(XendInner, YendInner); 
       p.arcTo(innerradiusPathRectF, (float)degrees - (float)90, -1 * (float)drawpercent * (float)DegreesRotation); 
       p.close(); 

       g.clipPath(p); 

       g.drawBitmap(bitmapCircularBarImage, bitmapRect0, bitmapRectXY, paint); 
2

作爲一個實驗,我試圖在Canvas上做同樣的事情。這是我想出了,利用一個的RadialGradient和功能GraphicsContext.fillArc的:

/** 
* 
* @param x Coordinate x of the centre of the arc 
* @param y Coordinate y of the centre of the arc 
* @param outer Outer radius of the arc 
* @param innerPercentage Inner radius of the arc, from 0 to 1 (as percentage) 
* @param arcStartAngle Start angle of the arc, in degrees 
* @param arcExtent Extent of the arc, in degrees 
*/ 
private void drawSemiCircle(float x, float y, float outer, float innerPercentage, float arcStartAngle, float arcExtent) { 
    RadialGradient rg = new RadialGradient(
      0, 
      0, 
      x, 
      y, 
      outer, 
      false, 
      CycleMethod.NO_CYCLE, 
      new Stop((innerPercentage + (.0 * innerPercentage)), Color.TRANSPARENT), 
      new Stop((innerPercentage + (.1 * innerPercentage)), Color.RED), 
      new Stop((innerPercentage + (.6 * innerPercentage)), Color.YELLOW), 
      new Stop((innerPercentage + (1 * innerPercentage)), Color.GREEN) 
    ); 
    gc.setFill(rg); 
    gc.fillArc(
      x - outer, 
      y - outer, 
      outer * 2, 
      outer * 2, 
      arcStartAngle, 
      arcExtent, 
      ArcType.ROUND 
    ); 
} 

這裏的關鍵點是弧型的ArcType.ROUND和使用Color.TRANSPARENT作爲第一種顏色。

然後,它可以用於一些沿線:

drawSemiCircle(100, 100, 100, .5f, -45, 270); 

這不是一個完美的解決方案,但它爲我工作。