Нарисуйте полукольцо-JavaFX
Я хотел бы знать, как нарисовать полукруг в JavaFX. Я попытался использовать форму и QuadCurve, но я не мог сделать идеальный полукруг.
вот картина того, что я пытаюсь нарисовать:
4 ответов
изображение, которое вы связали, на самом деле является полукольцом. Вы можете получить его в JavaFX, рисуя вложенные 2 дуги и некоторые линии. Но мой предпочтительный способ-использовать 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);
}
}
смотрите форма API JavaFX для получения дополнительной информации о формах, используемых в коде.
Скриншот:
предложения:
- Если вам не нужен полный наметив путь, вы можете просто использовать дугу.
- Если вам не нужна заполненная дуга и вы просто хотите проследить путь контура дуги, установите для заполнения дуги значение null.
- если вы хотите контурный путь дуги толщиной, то установите параметры хода на дуге.
- Если вам нужны толстые дуги, который также обозначил, то лучше, чтобы определить полную дугу, как в Улук по ответ.
пример кода:
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); }
}
в качестве эксперимента, я попробовал сделать то же самое на холсте. Это то, что я придумал, используя 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.Круглый и использование цвета.Прозрачный как первый цвет.
тогда его можно использовать что-то вдоль линии:
drawSemiCircle(100, 100, 100, .5f, -45, 270);
это не идеальное решение, но он работал для меня.
путь.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);