Reputation:
I'm working on a simple app and it features a pie chart. My goal is that if a user hovers their mouse over any section of the chart, it will expand and present more information. In my program, the chart is made of 3 arcs. Here's my code.
import javafx.scene.Group; //Maybe too many imports, I just use em all
import javafx.scene.Scene; //because I'm lazy
import javafx.stage.Stage;
import javafx.util.Duration;
import javafx.scene.paint.Color;
import javafx.scene.shape.Arc;
import javafx.scene.shape.Rectangle;
import javafx.event.EventHandler;
import javafx.event.ActionEvent;
import javafx.event.Event;
import javafx.application.Application;
import javafx.scene.shape.*;
import javafx.scene.shape.Line;
import javafx.scene.text.Text;
import javafx.scene.text.Font;
import javafx.scene.text.FontWeight;
import javafx.scene.input.MouseEvent;
import javafx.animation.ScaleTransition;
import java.lang.Thread;
public class AnimatingDemo extends Application{
public static void main(String[] args) {
launch(args);
}
@Override
public void start(Stage stage) {
//create 3 arc variables
Arc arc1 = new Arc();
Arc arc2 = new Arc();
Arc arc3 = new Arc();
//set up arc1 in place and to right color
arc1.setFill(Color.rgb(35,25,43,1.0));
arc1.setCenterX(250);
arc1.setCenterY(250);
arc1.setRadiusX(100.0f);
arc1.setRadiusY(100.0f);
arc1.setStartAngle(315);
arc1.setLength(-90);
arc1.setType(ArcType.ROUND);
//set up and color arc2
arc2.setFill(Color.rgb(39,70,144,1.0));
arc2.setCenterX(250);
arc2.setCenterY(250);
arc2.setRadiusX(100.0f);
arc2.setRadiusY(100.0f);
arc2.setStartAngle(90);
arc2.setLength(-135);
arc2.setType(ArcType.ROUND);
//set up and color arc3
arc3.setFill(Color.rgb(54,65,86,1.0));
arc3.setCenterX(250);
arc3.setCenterY(250);
arc3.setRadiusX(100.0f);
arc3.setRadiusY(100.0f);
arc3.setStartAngle(225);
arc3.setLength(-135);
arc3.setType(ArcType.ROUND);
//create root group
Group root = new Group();
//set up window
//add nodes to root
root.getChildren().addAll(arc1,arc2,arc3);
Scene scene = new Scene(root, 500,500);
stage.setTitle("Testing arc animation");
stage.setScene(scene);
stage.show();
}
}
This is just a sample I made so I can recreate the problem, but it gets the point across. I did research about various methods of animation in Javafx. The animation class seemed most viable, so I tried it in my program. I used the following code:
arc1.addEventFilter(MouseEvent.MOUSE_PRESSED, new EventHandler<MouseEvent>() {
@Override
public void handle(MouseEvent mouseEvent) {
ScaleTransition st = new ScaleTransition(Duration.millis(1500),arc1);
st.setByX(0.3);
st.setByY(0.3);
st.setCycleCount(1);
st.setAutoReverse(false);
st.play();
}
});
I repeated it 3 times for each arc but that's redundant here.
Anyway, the result is that both ends of the arc scale, so the pi chart looks messy and isn't centered anymore, also the scaling increases depending on the size of the arc so it's inconsistent.
I then decided to move onto a more basic method, using thread.sleep().
arc1.addEventFilter(MouseEvent.MOUSE_PRESSED, new EventHandler<MouseEvent>() {
@Override
public void handle(MouseEvent mouseEvent) {
for(int a = 0; a < 10; a++) {
try {
arc1.setRadiusX(arc1.getRadiusX() + 1);
arc1.setRadiusY(arc1.getRadiusY() + 1);
Thread.sleep(100);
}
catch(InterruptedException e) {
e.printStackTrace();
}
}
}
});
this doesn't work either, the circle just instantly expands by the given amount of units I wanted (instantly).
So my question is, what can I do? Is there a method to prevent the skewing in the animation class? Can I make the thread.sleep animation fluent in some way? Any advice helps, thank you for your time!
P.S. If it needs more comments let me know
Upvotes: 1
Views: 1040
Reputation: 1192
I'm not sure this is exactly what you are looking for, since you went with Arc
's instead of a proper PieChart
, but I used the PieChart
class and did everything you did and it works out just fine.
Here I took the PieChart.Data
class and made three separate ones just for testing.
I added an EventFilter
by calling .getNode()
on the PieChart.Data
variable, and then just pasted your method you supplied above.
Again, I assume there was a reason you used Arc
instead of PieChart
, but I got it to work this way.
@Override
public void start(Stage stage) {
ObservableList<PieChart.Data> data = FXCollections.observableArrayList();
PieChart pieChart = new PieChart(data);
PieChart.Data one = new PieChart.Data("one", 50.0);
PieChart.Data two = new PieChart.Data("two", 33.0);
PieChart.Data three = new PieChart.Data("three", 17.0);
data.addAll(one, two, three);
one.getNode().addEventFilter(MouseEvent.MOUSE_PRESSED, mouseEvent -> {
ScaleTransition st = new ScaleTransition(Duration.millis(1500),one.getNode());
st.setByX(0.3);
st.setByY(0.3);
st.setCycleCount(1);
st.setAutoReverse(false);
st.play();
});
two.getNode().addEventFilter(MouseEvent.MOUSE_PRESSED, mouseEvent -> {
ScaleTransition st = new ScaleTransition(Duration.millis(1500),two.getNode());
st.setByX(0.3);
st.setByY(0.3);
st.setCycleCount(1);
st.setAutoReverse(false);
st.play();
});
three.getNode().addEventFilter(MouseEvent.MOUSE_PRESSED, mouseEvent -> {
ScaleTransition st = new ScaleTransition(Duration.millis(1500),three.getNode());
st.setByX(0.3);
st.setByY(0.3);
st.setCycleCount(1);
st.setAutoReverse(false);
st.play();
});
//create root group
Group root = new Group();
//set up window
//add nodes to root
root.getChildren().addAll(pieChart);
Scene scene = new Scene(root, 500,500);
stage.setTitle("Testing arc animation");
stage.setScene(scene);
stage.show();
}
Upvotes: 1