Reputation: 291
I'm porting a class that that was previously done in Swing to JavaFX 8. It displays a UI element that looks like an analog electric voltage meter with a half circle surrounded by a collection of "tic marks" at regular intervals. In the Swing version the class was an extension of JPanel and the tic marks were drawn in paintComponent(Graphics g) as follows:
private Line2D ticLine = new Line2D.Float(0, LINE_ROOT_Y, TIC_LENGTH, LINE_ROOT_Y);
public void paintComponent(Graphics g)
{
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
// Draw tic marks
if (ticCount > 0)
{
g2.draw(ticLine); // First tic
AffineTransform ticTrans = new AffineTransform();
// Draw all additional tics rotated around half circle
for (int i = 1; i < ticCount; i++)
{
ticTrans.rotate(Math.toRadians(ticGap),
METER_MIDDLE, METER_BASE_Y);
g2.draw(ticTrans.createTransformedShape(ticLine));
}
}
}
This worked fine.
Now with JavaFX I'm using a class extending VBox. It contains 2 stacked Canvas objects. One of which will draw the static elements like the half circle and tic marks, and the other for the regularly moving meter line. On that first Canvas I was hoping to use a similar loop as I did in the Swing version to easily redraw the first tic mark in a ticCount # of additional positions around the half circle. So I tried the following which compiled and ran but only drew that first tic mark:
// Called from the constructor:
MeterGC = MeterCanvas.getGraphicsContext2D();
Line ticLine = new Line(0, LINE_ROOT_Y, TIC_LENGTH, LINE_ROOT_Y);
// Draw tic marks
if (ticCount > 1)
{
MeterGC.setStroke(Color.GRAY);
MeterGC.setLineWidth(BASIC_LINE_WIDTH);
MeterGC.strokeLine(ticLine.getStartX(), ticLine.getStartY(),
ticLine.getEndX(), ticLine.getEndY());
Rotate ticTrans = new Rotate(Math.toRadians(ticGap), METER_MIDDLE, METER_BASE_Y);
for (int i = 1; i < ticCount; i++)
{
ticLine.getTransforms().add(ticTrans);
MeterGC.strokeLine(ticLine.getStartX(), ticLine.getStartY(),
ticLine.getEndX(), ticLine.getEndY());
}
}
It may be that trying to Transform a Shape object like this only works when drawing to a scene and not on a Canvas. Or that I have to do something after the "ticLine.getTransforms().add(ticTrans)" line to get them to apply to the line. Am I at least close? Or is there a much better way to do what I'm trying here?
Upvotes: 0
Views: 2033
Reputation: 291
This is my revised for-loop and it works perfectly. Noticing that converting the angle in Rotate to radians is no longer necessary in JavaFX was also key in getting it to work.
for (int i = 1; i < ticCount; i++)
{
Rotate ticTrans = new Rotate(ticGap * i, METER_MIDDLE, METER_BASE_Y);
MeterGC.setTransform(ticTrans.getMxx(), ticTrans.getMyx(), ticTrans.getMxy(),
ticTrans.getMyy(), ticTrans.getTx(), ticTrans.getTy());
MeterGC.strokeLine(ticLine.getStartX(), ticLine.getStartY(),
ticLine.getEndX(), ticLine.getEndY());
}
Upvotes: 0
Reputation: 159291
What you are doing wrong
In your sample code you are applying the transform to a Line
object (which you never display).
How to fix it
You need to set the transform on the canvas GraphicsContext
before you stroke the line on the canvas.
Sample code
For an example, see:
/**
* Sets the transform for the GraphicsContext to rotate around a pivot point.
*
* @param gc the graphics context the transform to applied to.
* @param angle the angle of rotation.
* @param px the x pivot co-ordinate for the rotation (in canvas co-ordinates).
* @param py the y pivot co-ordinate for the rotation (in canvas co-ordinates).
*/
private void rotate(GraphicsContext gc, double angle, double px, double py) {
Rotate r = new Rotate(angle, px, py);
gc.setTransform(r.getMxx(), r.getMyx(), r.getMxy(), r.getMyy(), r.getTx(), r.getTy());
}
Upvotes: 1