Chciałbym wiedzieć, jak narysować półkole w JavaFX. Próbowałem użyć Shape i QuadCurve, ale nie mogłem stworzyć idealnego półkola.Narysuj pół pierścień - JavaFX
Oto obraz tego, co staram się rysować:
Chciałbym wiedzieć, jak narysować półkole w JavaFX. Próbowałem użyć Shape i QuadCurve, ale nie mogłem stworzyć idealnego półkola.Narysuj pół pierścień - JavaFX
Oto obraz tego, co staram się rysować:
obraz jesteś połączony jest właściwie pół-ring. Możesz pobrać go w JavaFX, rysując zagnieżdżone 2 łuki i niektóre linie. Ale moim preferowanym sposobem jest użycie 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);
}
}
Zapoznaj się z Shape API JavaFX, aby uzyskać więcej informacji o kształtach używanych w kodzie.
ekranu:
Sugestie:
Przykładowy kod:
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); }
}
Dziękuję, ale to pełne półkole, co chcę narysować to półkole puste w środku. W poprzednim poście umieściłem przykład pokazujący dokładnie to, co próbuję narysować. – AwaX
Zaktualizowana odpowiedź w celu zademonstrowania rysowania łuku z określonym obrysem i bez wypełnienia (które wygeneruje obraz pół-pierścieniowy). – jewelsea
Dziękuję bardzo za twoją aktualizację, twoje rozwiązanie jest wygodniejsze, ale nie możesz wypełnić łuku, tak jak powiedziałeś, więc myślę, że wezmę inne rozwiązanie. – AwaX
Path.arcTo() parametru SweepAngle odnosi się do stopnia obrotu, jeśli sweepAngle jest dodatni łuku ruchu wskazówek zegara, jeśli sweepAngle jest ujemny łuku w kierunku przeciwnym.
Kod ten jest używany w moim środowisku produkcyjnym, to zwraca pierścień półokrąg użyciu bitmapy, ścieżka idzie w prawo na zewnętrznym promieniu, a przeciwnie do ruchu wskazówek zegara na wewnętrznym promieniu:
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);
Jako eksperyment próbowałem zrobić to samo na płótnie. To jest to, co wymyśliłem, dzięki czemu korzystanie z RadialGradient a funkcja 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
);
}
Kluczowe punkty Oto typ łukowy ArcType.ROUND i wykorzystanie Color.TRANSPARENT jako pierwszego koloru.
Wtedy może on być stosowany coś wzdłuż linii:
drawSemiCircle(100, 100, 100, .5f, -45, 270);
Nie jest to idealne rozwiązanie, ale pracował dla mnie.
Rok, idealny! : D Dokładnie tego potrzebuję ^^ Dziękuję bardzo! – AwaX
Czy wiesz, czy istnieje prosty sposób modyfikacji punktu obrotu ścieżki? – AwaX
@AwaX path.setRotate (45); –