JFreeChart - RangeAxis autorange and don't start from 0 - java

In JFreeChart how can I ask the RangeAxis to be automatically 'optimize' itself?
Right now I have bunch of data to be displayed between 25.00 and 27.00, but the range always starts from 0 which does not look nice:
I've tried to set plot.getRangeAxis().setAutoRange(true), but it does not work. Of course I can calculate my min and max values then later I can set it with setRange(min, max), but is there any bundled function to do this?
Repro:
import org.jfree.chart.ChartPanel;
import org.jfree.chart.ChartFactory;
import org.jfree.chart.JFreeChart;
import org.jfree.ui.ApplicationFrame;
import org.jfree.ui.RefineryUtilities;
import org.jfree.chart.plot.CategoryPlot;
import org.jfree.chart.plot.PlotOrientation;
import org.jfree.data.category.DefaultCategoryDataset;
public class LineChart_AWT extends ApplicationFrame {
public LineChart_AWT( String applicationTitle , String chartTitle ) {
super(applicationTitle);
JFreeChart lineChart = ChartFactory.createLineChart(
chartTitle,
"Dates","Temperature",
createDataset(),
PlotOrientation.VERTICAL,
true,true,false);
CategoryPlot plot = (CategoryPlot) lineChart.getPlot();
//plot.getRangeAxis().setRange(25, 27);
//plot.getRangeAxis().setAutoRange(true);
ChartPanel chartPanel = new ChartPanel( lineChart );
chartPanel.setPreferredSize( new java.awt.Dimension( 560 , 367 ) );
setContentPane( chartPanel );
}
private DefaultCategoryDataset createDataset( ) {
DefaultCategoryDataset dataset = new DefaultCategoryDataset( );
dataset.addValue( 26.44,"Temperature","2019-08-18 00:00");
dataset.addValue( 26.2,"Temperature","2019-08-18 01:00");
dataset.addValue( 25.93,"Temperature","2019-08-18 02:00");
dataset.addValue( 25.71,"Temperature","2019-08-18 03:00");
dataset.addValue( 25.54,"Temperature","2019-08-18 04:00");
dataset.addValue( 25.42,"Temperature","2019-08-18 05:00");
dataset.addValue( 25.25,"Temperature","2019-08-18 06:00");
dataset.addValue( 25.19,"Temperature","2019-08-18 07:00");
dataset.addValue( 25.25,"Temperature","2019-08-18 08:00");
dataset.addValue( 25.36,"Temperature","2019-08-18 09:00");
dataset.addValue( 25.52,"Temperature","2019-08-18 10:00");
dataset.addValue( 25.86,"Temperature","2019-08-18 11:00");
dataset.addValue( 26.51,"Temperature","2019-08-18 12:00");
dataset.addValue( 26.82,"Temperature","2019-08-18 13:00");
return dataset;
}
public static void main( String[ ] args ) {
LineChart_AWT chart = new LineChart_AWT(
"X-axis demo" ,
"Y-range is wrong");
chart.pack( );
RefineryUtilities.centerFrameOnScreen( chart );
chart.setVisible( true );
}
}

In addition, it must be specified with NumberAxis#setAutoRangeIncludesZero whether the zero-value should be contained in the displayed interval:
plot.getRangeAxis().setAutoRange(true); // uncomment
((NumberAxis)plot.getRangeAxis()).setAutoRangeIncludesZero(false); // add
Results in:

Related

How to add data into a JFree XY chart every 5 seconds?

I have access to a database that returns the temperature of a location and time of that location every 5 seconds.
I have an idea of plotting the time on the x-axis.
And probably by using the java swing timer I would be able to add data into the graph every 5 seconds.
However, I do not know how to implement that because I thought of adding a timer in createDataset( ) but since it returns a dataset, I won't be able to achieve it.
Any idea how I would be able to add data into the graph every 5 seconds?
Here is my code:
import java.awt.Color;
import java.awt.BasicStroke;
import org.jfree.chart.ChartPanel;
import org.jfree.chart.JFreeChart;
import org.jfree.data.xy.XYDataset;
import org.jfree.data.xy.XYSeries;
import org.jfree.ui.ApplicationFrame;
import org.jfree.ui.RefineryUtilities;
import org.jfree.chart.plot.XYPlot;
import org.jfree.chart.ChartFactory;
import org.jfree.chart.plot.PlotOrientation;
import org.jfree.data.xy.XYSeriesCollection;
import org.jfree.chart.renderer.xy.XYLineAndShapeRenderer;
public class XYLineChart_AWT extends ApplicationFrame {
public XYLineChart_AWT( String applicationTitle, String chartTitle ) {
super(applicationTitle);
JFreeChart xylineChart = ChartFactory.createXYLineChart(
chartTitle ,
"Time" ,
"Temperature" ,
createDataset() ,
PlotOrientation.VERTICAL ,
true , true , false);
ChartPanel chartPanel = new ChartPanel( xylineChart );
chartPanel.setPreferredSize( new java.awt.Dimension( 560 , 367 ) );
final XYPlot plot = xylineChart.getXYPlot( );
XYLineAndShapeRenderer renderer = new XYLineAndShapeRenderer( );
renderer.setSeriesPaint( 0 , Color.RED );
renderer.setSeriesStroke( 0 , new BasicStroke( 4.0f ) );
plot.setRenderer( renderer );
setContentPane( chartPanel );
}
private XYDataset createDataset( ) {
final XYSeries temp = new XYSeries( "Temperature" );
//time = getTime(); //returns a float time in seconds.milliseconds
//temperature = getTemp(); //returns a number temperature
//I want to add data into temp every 5 seconds but i don't know how to do it
temp.add( 1.0 , 1.0 );
temp.add( 2.0 , 4.0 );
temp.add( 3.0 , 3.0 );
final XYSeriesCollection dataset = new XYSeriesCollection( );
dataset.addSeries( temp );
return dataset;
}
public static void main( String[ ] args ) {
XYLineChart_AWT chart = new XYLineChart_AWT("Temp",
"Temperature of some location");
chart.pack( );
RefineryUtilities.centerFrameOnScreen( chart );
chart.setVisible( true );
}
}
Rather than putting a timer in your createDataset() method you can instead spawn a new thread from your main method that modifies your JFreeChart dataset every 5 seconds.
For example you could do it something like this:
public static void main( String[ ] args ) {
XYLineChart_AWT chart = new XYLineChart_AWT("Temp",
"Temperature of some location");
chart.pack( );
RefineryUtilities.centerFrameOnScreen( chart );
chart.setVisible( true );
//now make your timer
int delay = 5000; //milliseconds
ActionListener timerAction = new ActionListener() {
public void actionPerformed(ActionEvent evt) {
//some code here to get and modify your dataset so it can be updated
// ----
// ----
//now apply your new dataset to your JFreeChart
xylineChart.getXYPlot().setDataset(myNewDataset);
}
};
new Timer(delay, timerAction).start();
}
Remember to add some code to remove old entries in your dataset so that the chart remains readable and all the values on the Time axis remain the same distance apart between different datasets, for example make sure there are no more than 24 items (2 minutes of data) plotted at a time.

JFreeChart StackedXYAreaRenderer causes "crimp" in chart

I'm using JFreeChart to show a stacked line chart of two sets of data over time, in this example dogs and cats.
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import javax.swing.JFrame;
import org.jfree.chart.ChartFactory;
import org.jfree.chart.ChartPanel;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.axis.DateAxis;
import org.jfree.chart.plot.PlotOrientation;
import org.jfree.chart.plot.XYPlot;
import org.jfree.chart.renderer.xy.StackedXYAreaRenderer;
import org.jfree.data.time.Minute;
import org.jfree.data.time.TimeTableXYDataset;
public class ChartTest {
public ChartTest() throws ParseException{
TimeTableXYDataset chartData = createChartData();
JFreeChart chart = createChart(chartData);
ChartPanel chartPanel = new ChartPanel(chart);
JFrame frame = new JFrame("Chart Test");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(chartPanel);
frame.setSize(500, 500);
frame.setVisible(true);
}
private TimeTableXYDataset createChartData() throws ParseException {
int[] dogs = {14, 81, 99, 89, 151, 263, 396, 548, 822, 1410, 2180, 3134, 4065, 5016, 6019, 7648, 9323, 11059, 12252, 13432, 15238, 17559, 19796, 21853, 23971, 26414, 28694, 31371, 34233, 37353, 40451, 44081, 47978, 52040, 56024, 60486, 64881, 69663, 74320, 79391, 84840, 91228, 96383, 102061, 107832, 114244, 119992, 126207, 132894, 139146, 144727, 150896, 156503, 161960, 167724, 174172, 180121, 185929, 191375, 196050, 200768, 205208, 208727, 212329, 216439, 221102, 224284, 226944, 230307, 233075, 234814, 236220, 237733, 239158, 240311, 241267};
int[] cats = {244, 360, 363, 644, 1075, 1516, 2241, 3160, 3591, 4661, 5633, 6990, 7889, 9059, 10510, 11743, 12506, 13540, 14557, 15705, 16969, 18350, 20197, 21659, 23160, 24840, 26394, 28109, 29742, 31428, 33021, 34514, 35822, 37339, 38784, 40258, 41568, 42921, 44180, 45454, 46710, 48084, 49418, 50712, 51920, 53014, 53923, 54830, 55756, 56573, 57554, 58352, 59064, 59874, 60933, 61948, 62762, 63299, 63772, 64243, 64789, 65206, 65693, 66016, 66391, 66859, 67432, 67919, 68400, 68677, 68944, 69211, 69511, 69786, 69990, 70279};
final TimeTableXYDataset chartData = new TimeTableXYDataset();
long start = new SimpleDateFormat("MM/dd/yyyy HH:mm").parse("11/08/2016 08:00").getTime();
for (int t = 0; t < dogs.length; t++) {
Minute m = new Minute(new Date(start + 15*t*60*1000));
chartData.add(m, dogs[t], "Dogs");
chartData.add(m, cats[t], "Cats");
}
return chartData;
}
private JFreeChart createChart(TimeTableXYDataset chartData) {
JFreeChart chart = ChartFactory.createStackedXYAreaChart("Dogs and Cats", "Time", "Count", chartData, PlotOrientation.VERTICAL, false, true, false);
StackedXYAreaRenderer chartRenderer = new StackedXYAreaRenderer();
XYPlot plot = (XYPlot)chart.getPlot();
plot.setRenderer(chartRenderer);
DateAxis dateAxis = new DateAxis();
dateAxis.setDateFormatOverride(new SimpleDateFormat("HH:mm"));
dateAxis.setTickLabelFont(dateAxis.getTickLabelFont().deriveFont(20f));
plot.setDomainAxis(dateAxis);
return chart;
}
public static void main(String... args) throws ParseException{
new ChartTest();
}
}
However, this results in a "crimp" in the cats section of the chart:
I've looked my data over, and it doesn't contain negative values or anything strange that might throw the chart off.
Through some shotgun debugging, I realized that if I remove this section of code from the createChart() function:
StackedXYAreaRenderer chartRenderer = new StackedXYAreaRenderer();
XYPlot plot = (XYPlot)chart.getPlot();
plot.setRenderer(chartRenderer);
DateAxis dateAxis = new DateAxis();
dateAxis.setDateFormatOverride(new SimpleDateFormat("HH:mm"));
dateAxis.setTickLabelFont(dateAxis.getTickLabelFont().deriveFont(20f));
plot.setDomainAxis(dateAxis);
Then I get a more reasonable stacked line chart:
But then I lose my nicely formatted dates.
My questions are:
What is causing the "crimp" in the cats section of the chart, and the space between the two stacks?
Is there a different way to format the dates that doesn't cause this behavior?
ChartFactory.createStackedXYAreaChart() instantiates StackedXYAreaRenderer2 to avoid this problem. Your example replaces it with an instance of StackedXYAreaRenderer. Either,
Use the factory's renderer and a custom DateAxis.
private JFreeChart createChart(TimeTableXYDataset chartData) {
JFreeChart chart = ChartFactory.createStackedXYAreaChart(
"Dogs and Cats", "Time", "Count", chartData,
PlotOrientation.VERTICAL, false, true, false);
DateAxis dateAxis = new DateAxis();
dateAxis.setDateFormatOverride(new SimpleDateFormat("HH:mm"));
dateAxis.setTickLabelFont(dateAxis.getTickLabelFont().deriveFont(20f));
XYPlot plot = (XYPlot) chart.getPlot();
plot.setDomainAxis(dateAxis);
return chart;
}
Recapitulate the factory, as shown here, in your createChart() method.
private JFreeChart createChart(TimeTableXYDataset chartData) {
DateAxis dateAxis = new DateAxis("Time");
dateAxis.setDateFormatOverride(new SimpleDateFormat("HH:mm"));
dateAxis.setTickLabelFont(dateAxis.getTickLabelFont().deriveFont(20f));
NumberAxis yAxis = new NumberAxis("Count");
XYToolTipGenerator toolTipGenerator = new StandardXYToolTipGenerator();
StackedXYAreaRenderer2 renderer = new StackedXYAreaRenderer2(
toolTipGenerator, null);
renderer.setOutline(true);
XYPlot plot = new XYPlot(chartData, dateAxis, yAxis, renderer);
plot.setOrientation(PlotOrientation.VERTICAL);
plot.setRangeAxis(yAxis); // forces recalculation of the axis range
JFreeChart chart = new JFreeChart("Dogs and Cats",
JFreeChart.DEFAULT_TITLE_FONT, plot, false);
new StandardChartTheme("JFree").apply(chart);
return chart;
}
Can you expand a little bit on why the StackedXYRenderer causes that crimp?
The author writes, "StackedXYAreaRenderer2 uses a different drawing approach, calculating a polygon for each data point and filling that." In contrast, StackedXYAreaRenderer appears to close a single Shape by connecting the endpoints with a straight line.

how can I embed 2 bars chart in html using java?

I generate html page with java using gagawa
I now try to add a charts like this:
I have tried org.jfree framework
with this code:
private Img createChart(LatencyHistogram current, LatencyHistogram baseLine) {
Img image = null;
final CategoryDataset dataset = createDataset(current, baseLine);
final JFreeChart chart = ChartFactory.createLineChart(
"Line Chart Demo 1", // chart title
"Type", // domain axis label
"Value", // range axis label
dataset, // data
PlotOrientation.VERTICAL, // orientation
true, // include legend
true, // tooltips
false // urls
);
chart.setBackgroundPaint(java.awt.Color.white);
// save it to an image
try {
final ChartRenderingInfo info = new ChartRenderingInfo(new StandardEntityCollection());
final String pathname = Constants.HTML_PAGES_PATH + "images/latency_delta.png";
final File file1 = new File(pathname);
ChartUtilities.saveChartAsPNG(file1, chart, 600, 400, info);
image = new Img("latency", "../images/latency_delta.png").setWidth("400");
return image;
} catch (IOException e) {
e.printStackTrace();
}
return image;
}
and got this result:
is there any way to create 2 bars chart instead?
is there a more clean and tidy free java charts drawer framework?
to create a bar chart you should use
ChartFactory.createBarChart()
instead of
ChartFactory.createLineChart()
method .but since i don't know what is LatencyHistogram in your code this is not exact code.you have to currently use those data types .
for example following code will generate this
example code
import java.awt.Color;
import org.jfree.chart.ChartFactory;
import org.jfree.chart.ChartPanel;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.plot.CategoryPlot;
import org.jfree.chart.plot.PlotOrientation;
import org.jfree.chart.renderer.category.BarRenderer;
import org.jfree.data.category.CategoryDataset;
import org.jfree.data.category.DefaultCategoryDataset;
import org.jfree.ui.ApplicationFrame;
import org.jfree.ui.RefineryUtilities;
public class BarChartx extends ApplicationFrame {
public BarChartx(String applicationTitle, String chartTitle) {
super(applicationTitle);
JFreeChart barChart = ChartFactory.createBarChart(chartTitle, "year", "value", createDataset(), PlotOrientation.VERTICAL, true, true, false);
CategoryPlot p = barChart.getCategoryPlot();
BarRenderer renderer = (BarRenderer) p.getRenderer();
renderer.setSeriesPaint(0, new Color(255, 0, 102));
renderer.setSeriesPaint(1, new Color(0, 153, 255));
renderer.setItemMargin(0.03);
ChartPanel chartPanel = new ChartPanel(barChart);
chartPanel.setPreferredSize(new java.awt.Dimension(560, 367));
setContentPane(chartPanel);
}
private CategoryDataset createDataset() {
final String apple = "apple";
final String mango = "mango";
final String y2000 = "2000";
final String y2001 = "2001";
final String y2002 = "2002";
final DefaultCategoryDataset dataset = new DefaultCategoryDataset();
dataset.addValue(700, apple, y2000);
dataset.addValue(550, mango, y2000);
dataset.addValue(700, apple, y2001);
dataset.addValue(550, mango, y2001);
dataset.addValue(720, apple, y2002);
dataset.addValue(570, mango, y2002);
return dataset;
}
public static void main(String[] args) {
BarChartx chart = new BarChartx("example", "Bar Chart Demo 1");
chart.pack();
RefineryUtilities.centerFrameOnScreen(chart);
chart.setVisible(true);
}
}

Adding values to JFreeChart XYDataset from csv file using opencsv

I am trying to read in a .csv file but I am stuck on how once I've read each line on the csv file and how to add it to the XYDataset.
My algorithm is as follows: read in .csv file -> read each line -> add to dataset -> create chart -> output as frame
data.csv has 4 columns: Time, X, Y, Z
How do I add each point (time,x), (time,y), (time,z) to the dataset?
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import org.jfree.chart.ChartFactory;
import org.jfree.chart.ChartPanel;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.plot.PlotOrientation;
import org.jfree.data.xy.XYDataset;
import org.jfree.data.xy.XYSeries;
import org.jfree.data.xy.XYSeriesCollection;
import org.jfree.ui.ApplicationFrame;
import org.jfree.ui.RefineryUtilities;
import com.opencsv.CSVReader;
public class Test extends ApplicationFrame
{
XYDataset dataset;
JFreeChart chart;
final ChartPanel chartPanel;
final int chartWidth = 560;
final int chartHeight = 367;
CSVReader reader;
String[] readNextLine;
XYSeries series;
public Test(String applicationTitle) throws IOException
{
super(applicationTitle);
dataset = createDataset();
chart = createChart(dataset);
chartPanel = new ChartPanel(chart);
chartPanel.setPreferredSize(new java.awt.Dimension(chartHeight, chartWidth));
}
public XYDataset createDataset() throws NumberFormatException, IOException
{
dataset = new XYSeriesCollection();
try
{
reader = new CSVReader(new FileReader("data.csv"));
while((readNextLine = reader.readNext()) != null)
{
if (readNextLine != null)
{
//add values to dataset
}
}
}
catch (FileNotFoundException e)
{
System.out.println("File not found!");
}
return dataset;
}
public JFreeChart createChart(XYDataset dataset) throws NumberFormatException, IOException
{
chart = ChartFactory.createXYLineChart(
"Acceleration vs Time", //chart title
"Time", //domain axis label
"Acceleration", //range axis label
createDataset(), //data
PlotOrientation.VERTICAL, //the plot orientation
true, //legend
true, //tooltips
false); //urls
return chart;
}
public static void main(String[] args) throws IOException
{
final Test demo = new Test("Test XY Line chart");
demo.pack();
RefineryUtilities.centerFrameOnScreen(demo);
demo.setVisible(true);
}
}
The first 10 lines of my dataset look like this:
time x y z
0.003 -0.13 0.83 0.6
0.009 -0.12 0.83 0.61
0.012 -0.12 0.82 0.6
0.018 -0.13 0.81 0.61
0.021 -0.13 0.8 0.61
0.025 -0.12 0.8 0.61
0.033 -0.12 0.79 0.6
0.034 -0.11 0.79 0.6
0.039 -0.11 0.79 0.58
0.044 -0.11 0.77 0.57
Where your comment is - you need to first go through the elements of readNextLine where each element of the String[] will contain the value from your file for a given row (assuming your file is correctly formatted as you said). So - you need to turn these into variables. You haven't specified what format these are in, or what data type Time,X, Y and Z are.
Given that you're looking at an XY chart and your axes are labelled Time and acceleration - I'm going to guess that they're all Floating Point numbers, with Time in decimal seconds and the other variables as accelerations in the various axes. NOTE - if this assumption is wrong - you might need to use a different converter such as Integer.valueOf(), but the principle is the same.
before your while loop, set up the series that you want to add to. You'll add to them row by row within the while loop
final XYSeries seriesX = new XYSeries("X");
final XYSeries seriesY = new XYSeries("Y");
final XYSeries seriesZ = new XYSeries("Z");
within the while loop where your comment is
//add values to dataset
double Time = Double.valueOf(readNextLine[0]);
double X = Double.valueOf(readNextLine[1]);
double Y = Double.valueOf(readNextLine[2]);
double Z = Double.valueOf(readNextLine[3]);
seriesX.add(Time, X);
seriesY.add(Time, Y);
seriesZ.add(Time, Z);
and after the while loop add the 3 series to the collection before you return it:
dataset.addSeries(seriesX);
dataset.addSeries(seriesY);
dataset.addSeries(seriesZ);
Lastly - two comments
Your logic is a little weird around dataset creation. In your constructor, you create the dataset and pass it to createChart(). This is quite standard. But you then call createDataset() inline within the call to ChartFactory.createXYLineChart(, thus rendering the first creation of data pointless and doing it all again. It will work, but is wasteful and might be masking something else that you're intending the code to do.
The if check in createDataset() is redundant - you're already in a while loop based on a condition which means it will always be true.
if (readNextLine != null)
{
EDIT - added full working version to clear confusion in several comments
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import org.jfree.chart.ChartFactory;
import org.jfree.chart.ChartPanel;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.plot.PlotOrientation;
import org.jfree.data.xy.XYDataset;
import org.jfree.data.xy.XYSeries;
import org.jfree.data.xy.XYSeriesCollection;
import org.jfree.ui.ApplicationFrame;
import org.jfree.ui.RefineryUtilities;
import au.com.bytecode.opencsv.CSVReader;
public class Test extends ApplicationFrame {
/**
*
*/
private static final long serialVersionUID = 1L;
XYSeriesCollection dataset;
JFreeChart chart;
final ChartPanel chartPanel;
final int chartWidth = 560;
final int chartHeight = 367;
CSVReader reader;
String[] readNextLine;
XYSeries series;
public Test(String applicationTitle) throws IOException {
super(applicationTitle);
dataset = createDataset();
chart = createChart(dataset);
chartPanel = new ChartPanel(chart);
chartPanel.setPreferredSize(new java.awt.Dimension(chartHeight,
chartWidth));
this.add(chartPanel);
}
public XYSeriesCollection createDataset() throws NumberFormatException,
IOException {
dataset = new XYSeriesCollection();
try {
reader = new CSVReader(new FileReader("res\\data.csv"),'\t');
// Read the header and chuck it away
readNextLine = reader.readNext();
// Set up series
final XYSeries seriesX = new XYSeries("X");
final XYSeries seriesY = new XYSeries("Y");
final XYSeries seriesZ = new XYSeries("Z");
while ((readNextLine = reader.readNext()) != null) {
// add values to dataset
double Time = Double.valueOf(readNextLine[0]);
double X = Double.valueOf(readNextLine[1]);
double Y = Double.valueOf(readNextLine[2]);
double Z = Double.valueOf(readNextLine[3]);
seriesX.add(Time, X);
seriesY.add(Time, Y);
seriesZ.add(Time, Z);
}
System.out.println(seriesX.getMaxX() + "; " + seriesX.getMaxY());
dataset.addSeries(seriesX);
dataset.addSeries(seriesY);
dataset.addSeries(seriesZ);
} catch (FileNotFoundException e) {
System.out.println("File not found!");
}
return dataset;
}
public JFreeChart createChart(XYDataset dataset)
throws NumberFormatException, IOException {
chart = ChartFactory.createXYLineChart("Acceleration vs Time", // chart
// title
"Time", // domain axis label
"Acceleration", // range axis label
dataset, // data
PlotOrientation.VERTICAL, // the plot orientation
true, // legend
true, // tooltips
false); // urls
return chart;
}
public static void main(String[] args) throws IOException {
System.out.println("In here, to create a Test");
final Test demo = new Test("Test XY Line chart");
System.out.println("Created, pakcking");
demo.pack();
RefineryUtilities.centerFrameOnScreen(demo);
demo.setVisible(true);
}
}
Output with OP supplied first 10 data points

Two simultaneous RotationTransitions on the same node

I've been playing with animations while getting acquainted with JavaFX 2.0, and I wrote a small test program that was intended to rotate a rectangle along its X and Y axes. Here is the test program:
import javafx.animation.Animation;
import javafx.animation.FadeTransition;
import javafx.animation.ParallelTransition;
import javafx.animation.RotateTransition;
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.layout.BorderPane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Rectangle;
import javafx.scene.shape.RectangleBuilder;
import javafx.scene.transform.Rotate;
import javafx.stage.Stage;
import javafx.util.Duration;
public class ParallelTransitionTest extends Application
{
public static void main( String[] args )
{
launch( args );
}
#Override
public void start( Stage primaryStage ) throws Exception
{
init( primaryStage );
primaryStage.show();
}
private void init( Stage primaryStage )
{
primaryStage.setTitle( "Parallel Transition" );
primaryStage.setResizable( true );
// Create the scene
BorderPane root = new BorderPane();
Scene scene = new Scene( root, 800, 600, true );
scene.setFill( Color.BLACK );
primaryStage.setScene( scene );
Rectangle rect = RectangleBuilder.create()
.width( 100 ).height( 100 )
.x( 350 ).y( 250 )
.fill( Color.BLUE )
.build();
RotateTransition rotationY = new RotateTransition();
rotationY.setAxis( Rotate.Y_AXIS );
rotationY.setDuration( Duration.seconds( 5 ) );
rotationY.setByAngle( 360 );
rotationY.setNode( rect );
rotationY.setAutoReverse( true );
rotationY.setCycleCount( Animation.INDEFINITE );
RotateTransition rotationX = new RotateTransition();
rotationX.setAxis( Rotate.X_AXIS );
rotationX.setDuration( Duration.seconds( 5 ) );
rotationX.setByAngle( 360 );
rotationX.setNode( rect );
rotationX.setAutoReverse( true );
rotationX.setCycleCount( Animation.INDEFINITE );
FadeTransition fade = new FadeTransition();
fade.setDuration( Duration.seconds( 5 ) );
fade.setToValue( 0.2 );
fade.setNode( rect );
fade.setAutoReverse( true );
fade.setCycleCount( Animation.INDEFINITE );
ParallelTransition transition = new ParallelTransition( rect,
rotationX, rotationY, fade );
transition.setAutoReverse( true );
transition.play();
root.getChildren().add( rect );
}
}
Unfortunately, the rotation is only happening for one of the axes. My assumption is that both RotationTransitions are running, but that one is overwriting the rotation applied by the other. Is this the intended behavior of RotationTransition?
Also, if the following three lines are commented:
rotationY.setNode( rect );
...
rotationX.setNode( rect );
...
fade.setNode( rect );
I get a NullPointerException. The docs suggest that you shouldn't need to set the nodes on transitions included in a ParallelTransition. Is this a bug?
You should create another node add your rect to that node, and then:
RotateTransition rotationY = new RotateTransition();
rotationY.setAxis( Rotate.Y_AXIS );
rotationY.setDuration( Duration.seconds( 5 ) );
rotationY.setByAngle( 360 );
rotationY.setNode( rect );
rotationY.setAutoReverse( true );
rotationY.setCycleCount( Animation.INDEFINITE );
RotateTransition rotationX = new RotateTransition();
rotationX.setAxis( Rotate.X_AXIS );
rotationX.setDuration( Duration.seconds( 5 ) );
rotationX.setByAngle( 360 );
rotationX.setNode( NEWNODE );
rotationX.setAutoReverse( true );
rotationX.setCycleCount( Animation.INDEFINITE );

Categories