I would like to cut down in code by using the same variable name for two possible objects (JavaFX Chart objects in this case). The reason for this is because after this for loop some processing to the chart happens that is identically.
I tried downcasting the chart but it gives me an "unknown class" error.
Chart chart;
if (chartClass.equals(LineChart.class))
chart = new LineChart<Number, Number>(xAxis, yAxis);
else
chart = new AreaChart<Number, Number>(xAxis, yAxis);
for (int i = 0; i < variablesToPlot.length; i++) {
series[i] = new LineChart.Series<Number, Number>();
// this chart must be LineChart or AreaChart (but not general chart) for getData() to work
((chartClass) chart).getData().add(series[i]);
}
// here some chart processing that is equal for both charts
What I am looking for kind of sounds like dynamic typing (which Java is not capable of as far as I know), but is there a way to solve this problem other than writing the code twice?
Change the declaration of Chart chart to XYChart chart.
The common superclass of LineChart and AreaChart is XYChart.
You will then be able to cast it to XYChart and use the getData method on it.
It will result in:
XYChart chart;
if (chartClass.equals(LineChart.class))
chart = new LineChart<Number, Number>(xAxis, yAxis);
else
chart = new AreaChart<Number, Number>(xAxis, yAxis);
for (int i = 0; i < variablesToPlot.length; i++) {
series[i] = new LineChart.Series<Number, Number>();
// this chart must be LineChart or AreaChart (but not general chart) for getData() to work
chart.getData().add(series[i]);
}
Related
How to write a java library that would display graphs (charts) with large datasets (100-200 thousand points)? I think that such a large graph does not need to be displayed entirely, I probably only need to display a part of it, for example, a thousand points. But I need to be able to move around the graph and scale it.
It is also necessary that the charts are built in real time. As I understand it, for any action with the chart, the data must be displayed again, that is, thereby updated.
Maybe for speed it will be possible to do parallel execution of some parts of the code for drawing the chart. Because the speed of execution will be the main thing in this library.
I also plan to convert the chart to svg to be inserted into the html page.
Now I just build a graph using JavaFX, and it is very slow to build on a couple of thousand points and JavaFX does not seem to have tools for scaling.
public class FXLineChart {
private List<Long> dataset;
public FXLineChart(List<Long> dataset) {
this.dataset = dataset;
}
public void drawChart(Stage stage) {
stage.setTitle("Chart");
final NumberAxis xAxis = new NumberAxis();
final NumberAxis yAxis = new NumberAxis();
final LineChart<Number, Number> lineChart =
new LineChart<Number, Number>(xAxis, yAxis);
lineChart.setTitle("Check dataset");
XYChart.Series series = new XYChart.Series();
for (int i = 0; i < dataset.size(); i++) {
series.getData().add(new XYChart.Data(i, dataset.get(i)));
}
lineChart.getData().add(series);
Scene scene = new Scene(lineChart, 800, 600);
stage.setScene(scene);
stage.show();
}
}
JFreeChart is slightly better, but the chart slows down at several tens of thousands of points. I did not find information about real time in JFreeChart.
Maybe someone has a code for a similar task or idea? The challenge is that according to the assignment it should be its own library.
This question already has an answer here:
Fix spacing between different series in JavaFX line chart
(1 answer)
Closed 3 years ago.
I have this code:
public static void main(String[] args){ launch(args); }
#Override
public void start(Stage primaryStage){
NumberAxis xAxis = new NumberAxis(0, 23, 1);
xAxis.setLabel("XX");
NumberAxis yAxis = new NumberAxis();
yAxis.setLabel("YY");
LineChart<Number, Number> lineChart = new LineChart<>(xAxis, yAxis);
XYChart.Series<Number, Number> series1 = new XYChart.Series<>();
series1.setName("Loooooooooooooongest");
XYChart.Series<Number, Number> series2 = new XYChart.Series<>();
series2.setName("Short");
XYChart.Series<Number, Number> series3 = new XYChart.Series<>();
series3.setName("Loooooong");
lineChart.getData().addAll(series1, series2, series3);
primaryStage.setScene(new Scene(lineChart));
primaryStage.sizeToScene();
primaryStage.centerOnScreen();
primaryStage.show();
}
It looks like this:
Every legend has allocated space like the longest legend.
How I can remove all that space?
You can probably use a CSS Property. Maybe something like -fx-padding or -fx-margin. Not sure right now.
This could give you a good idea about for using CSS Properties in JavaFX: How to set specific color to JavaFX XYChart.Series?
Also it's a great idea to use the JavaFX-SceneBuilder. You can apply CSS there and directly see what it does.
I generated a BarChart in JavaFx using code(without SceneBuilder) and it fails to display double values on NumberAxis.I tried with int,long and short values and it works fine, but for some reason I cannot configure it to work with real numbers.
Here is my code:
private BarChart<String, Number> createBarChartMedii(Map<Student, Double> studentAndAverageGrades) {
CategoryAxis xAxis = new CategoryAxis();
xAxis.setLabel("Student");
NumberAxis yAxis = new NumberAxis();
yAxis.setLabel("Average");
BarChart<String, Number> barChart = new BarChart<>(xAxis, yAxis);
barChart.setTitle("Grades Average");
XYChart.Series<String, Number> series = new XYChart.Series<>();
studentAndAverageGrades.forEach((student, average) -> {
series.getData().add(new XYChart.Data<>(student.getNume(),average));
});
barChart.getData().addAll(series);
return barChart;
}
This is the output:
click for image
If I modify the line which adds data into the series(inside the lambda function in foreach) with this one:
series.getData().add(new XYChart.Data<>(student.getNume(),average.intValue()));
it populates the BarChart
Hi im trying to create a chart that is a combination of a bar chart and a line chart in JFree chart. The bar chart is vs time and for each hour it will compare two (or more) different values.
The line chart uses the same scale as the bar chart and shows the overall trend of the data set.
You can plot each dataset on the same Plot, and use a different renderer for each dataset (for instance a BarRenderer and LineAndShapeRenderer). Below is a simplified example that generates some mock data values (1-9) and renders the same data as both bars and lines on the same ChartPanel.
//Mock data
DefaultCategoryDataset dataset = new DefaultCategoryDataset();
int[] times = new int[]{1,2,3,4,5,6,7,8,9};
for ( int i = 0; i < times.length; i++ ){
dataset.addValue(times[i], "Time", "Hour" + String.valueOf(i+1));
}
//create the plot
CategoryPlot plot = new CategoryPlot();
//add the first dataset, and render as bar values
CategoryItemRenderer renderer = new BarRenderer();
plot.setDataset(0,dataset);
plot.setRenderer(0,renderer);
//add the second dataset, render as lines
CategoryItemRenderer renderer2 = new LineAndShapeRenderer();
plot.setDataset(1, dataset);
plot.setRenderer(1, renderer2);
//set axis
plot.setDomainAxis(new CategoryAxis("Time"));
plot.setRangeAxis(new NumberAxis("Value"));
And the resulting Chart:
I am working on graph chart using aChartEngine, the problem faced is that the although graph are generating, problem is graph is not coming as per need inside the view, how to fix it ??
When selecting Bar from drop down
After Zooming Out and panning(by interacting with graph)
Here is my code
private static XYMultipleSeriesDataset getBarDataset(int rightAnswers, int wrongAnswers)
{
String[] labels={"right","wrong"};
List<Double> values = new ArrayList<Double>();
values.add((double) rightAnswers);
values.add((double) wrongAnswers);
XYMultipleSeriesDataset dataset = new XYMultipleSeriesDataset();
for (int i = 0; i < titles.length; i++)
{
XYSeries series = new XYSeries(titles[i]);
series.add(i,values.get(i));
dataset.addSeries(i,series);
}
return dataset;
}
2)Renderer
protected static XYMultipleSeriesRenderer buildBarRenderer(int[] colors) {
XYMultipleSeriesRenderer renderer = new XYMultipleSeriesRenderer();
renderer.addXTextLabel(0, "right");
renderer.addXTextLabel(1, "wrong");
renderer.setChartTitle("Results");
int length = colors.length;
SimpleSeriesRenderer r = new SimpleSeriesRenderer();
r.setColor(colors[0]);
renderer.addSeriesRenderer(r);
r = new SimpleSeriesRenderer();
r.setColor(colors[1]);
renderer.addSeriesRenderer(r);
renderer.setScale(10);
renderer.setXLabels(0);
renderer.setApplyBackgroundColor(true);
renderer.setBackgroundColor(Color.WHITE);
renderer.setAxesColor(Color.CYAN);
renderer.setBarWidth(30);
return renderer;
}
3) the view
ChartFactory.getBarChartView(context, getBarDataset(rightAnswers, wrongAnswers), buildBarRenderer(new int[]{Color.GREEN,Color.RED}), Type.DEFAULT);
Query
1) How to fix the position and exact panned graph
2) Can we have 3d effect on bars??How??
3) Is there any other library simpler compared to aChartEngine??
To solve the problem of having bar inside the graph we need to specify X-axis and Y-axis min and max based on your minimum and maximum values,eg; for the renderer, you need
renderer.setXAxisMin(-1);
renderer.setXAxisMax(wrongAnswers);
renderer.setYAxisMax(10);
renderer.setYAxisMin(0);
so the final result comes out to be