Hello I have added data to a XYSeries and am trying to get that data sorted from shortest length to largest. I don't know how to manipulate this data, Can anyone help me out. This is my code:
xLabel = "Link Id";
yLabel = "Length (Km)";
bc = new BarChart<>(xAxis,yAxis);
bc.setTitle(gTitle);
//Set x/y Axis Label
//xAxis.setLabel(xLabel);
yAxis.setLabel(yLabel);
//double[] lengthArray = new double[linkIds.length];
XYChart.Series series1 = new XYChart.Series();
series1.setName(xLabel);
for (Integer m = 0; m < linkIdsOTS.length; m++) {
double length = netPlan.getLinkLengthInKm(otsLayerId, m);
//lengthArray[i] = length;
series1.getData().add(new XYChart.Data(m.toString(), length));
}
bc.getData().addAll(series1);
Assuming your Series and Data are properly typed, you should be able to do
series1.getData().sort(Comparator.comparingDouble(d -> d.getYValue().doubleValue()));
SSCCE:
import java.util.Comparator;
import java.util.Random;
import java.util.stream.Stream;
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.chart.BarChart;
import javafx.scene.chart.CategoryAxis;
import javafx.scene.chart.NumberAxis;
import javafx.scene.chart.XYChart.Data;
import javafx.scene.chart.XYChart.Series;
import javafx.stage.Stage;
public class BarChartSortTest extends Application {
#Override
public void start(Stage primaryStage) {
Random rng = new Random();
BarChart<String, Number> chart = new BarChart<>(new CategoryAxis(), new NumberAxis());
String cats = "ABCDEFGH" ;
Series<String, Number> series = new Series<>();
series.setName("Random data");
chart.getData().add(series);
Stream.of(cats.split(""))
.map(cat -> new Data<String, Number>(cat, rng.nextDouble()))
.forEach(series.getData()::add);
series.getData().sort(Comparator.comparingDouble(d -> d.getYValue().doubleValue()));
primaryStage.setScene(new Scene(chart, 600, 600));
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
Related
I would like to add y and x axis lines to my graph. I have tried by setting domain cross hairs by true, but it doesn't appear. Please could i have some help? when I run the program the graph comes up the x and y lines don't appear at x = 0 and y = 0:
plot.setDomainCrosshairVisible(true);
plot.setRangeCrosshairVisible(true);
package Grava;
import javafx.application.Application;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.TextField;
import javafx.scene.paint.Color;
import org.jfree.chart.axis.NumberAxis;
import javafx.scene.control.*;
import javafx.scene.image.Image;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.HBox;
import javafx.stage.Stage;
import org.jfree.chart.ChartFactory;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.fx.ChartViewer;
import org.jfree.chart.panel.CrosshairOverlay;
import org.jfree.chart.plot.XYPlot;
import org.jfree.chart.axis.NumberTickUnit;
import org.jfree.chart.axis.NumberAxis;
import org.jfree.chart.axis.NumberTickUnit;
import org.jfree.chart.plot.PlotOrientation;
import org.jfree.chart.plot.Crosshair;
import org.jfree.chart.renderer.xy.XYLineAndShapeRenderer;
import org.jfree.data.statistics.Regression;
import org.jfree.data.xy.XYSeries;
import org.jfree.data.xy.XYSeriesCollection;
import java.awt.*;
public class ScatterAdd extends Application {
private final XYSeries series = new XYSeries("Voltage");
private final XYSeries trend = new XYSeries("Trend");
private final XYSeriesCollection dataset = new XYSeriesCollection(series);
ChoiceBox<String> domainLabels = new ChoiceBox<>();
ChoiceBox<String> rangeLabels = new ChoiceBox<>();
private JFreeChart createChart() {
XYSeriesCollection dataset = new XYSeriesCollection();
dataset.addSeries(series);
return ChartFactory.createScatterPlot("VI Characteristics", "Current", "Voltage", dataset);
}
#Override
public void start(Stage stage) {
Image image = new Image("Grava.logo.png");
stage.getIcons().add(image);
XYPlot plot = createChart().getXYPlot();
plot.setDomainCrosshairVisible(true);
plot.setRangeCrosshairVisible(true);
XYLineAndShapeRenderer r = (XYLineAndShapeRenderer) plot.getRenderer();
r.setSeriesLinesVisible(1, Boolean.TRUE);
r.setSeriesShapesVisible(1, Boolean.FALSE);
var equation = new TextField();
series.addChangeListener((event) -> {
double[] coefficients = Regression.getOLSRegression(dataset, 0);
double b = coefficients[0]; // intercept
double m = coefficients[1]; // slope
equation.setText("y = " + m + " x + " + b);
});
JFreeChart chart = createChart();
domainLabels.getSelectionModel().selectedItemProperty().addListener((ov, s0, s1) -> {
chart.getXYPlot().getDomainAxis().setLabel(s1);
});
rangeLabels.getSelectionModel().selectedItemProperty().addListener((ov, s0, s1) -> {
chart.getXYPlot().getRangeAxis().setLabel(s1);
});
domainLabels.getItems().addAll("Current", "Seconds");
domainLabels.setValue("Current");
rangeLabels.getItems().addAll("Voltage", "Metres");
rangeLabels.setValue("Voltage");
var xSpin = new Spinner<Double>(-10000000.000, 10000000.000, 0, 0.1);
xSpin.setEditable(true);
xSpin.setPromptText("Xvalue");
var ySpin = new Spinner<Double>(-10000000.000, 10000000.000, 0, 0.1);
ySpin.setEditable(true);
ySpin.setPromptText("Yvalue");
var button = new Button("Add");
button.setOnAction(ae -> series.add(xSpin.getValue(), ySpin.getValue()));
HBox xBox = new HBox();
xBox.getChildren().addAll(domainLabels);
HBox yBox = new HBox();
yBox.getChildren().addAll(rangeLabels);
var enter = new ToolBar(xBox, xSpin, yBox, ySpin, button, equation);
BorderPane.setAlignment(enter, Pos.CENTER);
BorderPane root = new BorderPane();
root.setCenter(new ChartViewer(chart));
root.setBottom(enter);
stage.setTitle("ScatterAdd");
stage.setScene(new Scene(root, 720, 480));
stage.show();
}
/*
private void adjustAxis(NumberAxis axis, boolean vertical) {
axis.setRange(-3.0, 3.0);
axis.setTickUnit(new NumberTickUnit(0.5));
axis.setVerticalTickLabels(vertical);
}
*/
public static void main(String[] args) {
launch(args);
}
}
The crosshairs do not appear because you invoke createChart() twice, updating one instance while displaying the other. Instead, create and update a single instance:
public void start(Stage stage) {
//XYPlot plot = createChart().getXYPlot();
var chart = createChart();
XYPlot plot = chart.getXYPlot();
plot.setDomainCrosshairVisible(true);
plot.setRangeCrosshairVisible(true);
…
//JFreeChart chart = createChart();
…
}
Incidentally, adding the SeriesChangeListener before creating the chart, as you did here, risks causing Regression to
throw new IllegalArgumentException("Not enough data.");
Consider limiting the effect to two or more items:
series.addChangeListener((event) -> {
if (series.getItemCount() > 1) {
…
}
});
I need some help if you can spare a few minutes.
I am in a bit of a pickle as I try to make this work.
I have a javaFX class like this
import javafx.application.Application;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.StackPane;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
public class FoorballTeam extends Application {
int i1=0;
int i3=0;
String[] PlayerNames = new String[12];
int[] goals = new int[12];
#Override
public void start(Stage primaryStage) {
player[] playerData = new player[12];
Button btn = new Button();
btn.setText("add Player");
GridPane root = new GridPane();
root.add(btn,0,0);
int i2;
for (i2=0;i2<=11;i2++)
{playerData[i2]=new player();}
btn.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent event) {
playerData[i3].player(root, i3);
i3++;
}
});
Scene scene = new Scene(root, 300, 250);
primaryStage.setTitle("Hello World!");
primaryStage.setScene(scene);
primaryStage.show();
}
public String[] getPlayerNames() {
return PlayerNames;
}
public void setPlayerNames(String[] PlayerNames) {
this.PlayerNames = PlayerNames;
}
public int[] getGoals() {
return goals;
}
public void setGoals(int[] goals) {
this.goals = goals;
}
/**
* #param args the command line arguments
*/
public static void main(String[] args) {
launch(args);
}
}
and a second class named player like this
import javafx.event.EventType;
import javafx.scene.control.TextField;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.StackPane;
public class player {
String NameOfPlayer = new String();
int goalsOfPlayer;
public void player (GridPane root,int numberOfPlayer)
{
TextField name = new TextField();
TextField goals = new TextField();
GridPane grid = new GridPane();
grid.add(name,0,0);
grid.add(goals,1,0);
root.add(grid,0,numberOfPlayer+1);
System.out.println("player " + numberOfPlayer + " added");
name.textProperty().addListener((observable, oldValue, newValue) -> {
NameOfPlayer=newValue;
});
goals.textProperty().addListener((observable, oldValue, newValue) -> {
goalsOfPlayer=Integer.parseInt(newValue);
});
}
}
I want every time that I make a change to a players name or goals to pass this change on the two arrays PlayerNames[] and goals[] of the main class.
for example if player1 changes goals from 1 to 2 I want the goals[1]=2.
Also is it possible to put a listener to this two arrays so when a player changes name or goals to trigger the listener.
Any help will be appreciated.
One simple solution is to warp the int[] array with an observable list, and listen to changes in this list :
import java.util.Arrays;
import java.util.Random;
import javafx.application.Application;
import javafx.collections.FXCollections;
import javafx.collections.ListChangeListener;
import javafx.collections.ObservableList;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.GridPane;
import javafx.stage.Stage;
public class ListenToArrayCahnges extends Application {
private final int SIZE = 12;
private final Integer[] goals = new Integer[SIZE];
private final Random rand = new Random();
private int counter = 0;
#Override
public void start(Stage primaryStage) {
Arrays.fill(goals, 0); //initial values
//Warp array with an observable list. list back by array so it is of fixed length
ObservableList<Integer> goalsList = FXCollections.observableArrayList(Arrays.asList(goals));
//add listener to list
goalsList.addListener((ListChangeListener<Integer>) c ->{
//respond to list changes
System.out.println("Goals changed to : "+ goalsList);
});
//button to change the list
Button btn = new Button();
btn.setText("Add goal");
btn.setOnAction(event -> {
goalsList.set(counter, rand.nextInt(100));
counter = ++counter % SIZE ; //increment counter 0,1,2....11 and back to 0
});
GridPane root = new GridPane();
root.add(btn,0,0);
Scene scene = new Scene(root, 150, 50);
primaryStage.setTitle("Hello World!");
primaryStage.setScene(scene);
primaryStage.show();
}
/**
* #param args the command line arguments
*/
public static void main(String[] args) {
launch(args);
}
}
Note that the posted mcve represents the problem that needs to be solved (or in this case a solution to it), and not the specific application or use case.
I am trying to display a JavaFX multi-line chart. I try to open this graph on a Jbutton click from another Jframe and pass a data array to the graph class.
How can I make this class into an object and have it show the graph when the Jbutton is clicked from another Jfame?
This is my edited code and two arrays showing temporary data.
import javafx.application.Application;
import javafx.geometry.Side;
import javafx.scene.Scene;
import javafx.scene.chart.CategoryAxis;
import javafx.scene.chart.LineChart;
import javafx.scene.chart.NumberAxis;
import javafx.scene.chart.XYChart;
import javafx.stage.Stage;
public class LineGrph extends Application {
#Override
public void start(Stage stage) {
double LE[] = {23.5,12.0,44.0,12.6,8.5,4.6,53.6}; // this two arrays should pass from another Jframe
double RE[] = {22.5,32.0,40.0,32.6,43.5,23.6,11.6};
stage.setTitle("Line Chart Sample");
final CategoryAxis xAxis = new CategoryAxis();
final NumberAxis yAxis = new NumberAxis();
xAxis.setLabel("Hz");
yAxis.setLabel("DB");
xAxis.setSide(Side.TOP);
final LineChart<String,Number> lineChart =
new LineChart<String,Number>(xAxis,yAxis);
lineChart.setTitle("Stock Monitoring, 2010");
XYChart.Series series1 = new XYChart.Series();
series1.setName("Portfolio 1");
int count = 125;
for (int i = 0; i<= 6 ; i++)
{
String x = Integer.toString(count);
series1.getData().add(new XYChart.Data(x, LE[i]));
count = count * 2;
}
XYChart.Series series2 = new XYChart.Series();
series2.setName("Portfolio 2");
int count2 = 125;
for (int p = 0; p<= 6 ; p++)
{
String x = Integer.toString(count2);
series2.getData().add(new XYChart.Data(x, RE[p]));
count2 = count2 * 2;
}
Scene scene = new Scene(lineChart,800,600);
lineChart.getData().addAll(series1, series2);
stage.setScene(scene);
stage.show();
}
public static void main(String[] args) {
Application.launch(args);
}
}
I'm using this example http://docs.oracle.com/javafx/2/ui_controls/table-view.htm where tableview is based on MapValueFactory.
Now I have the situation when edited values are not saved. My actions:
Press "Enter" -> type new value -> press "Enter" again -> Result: New value is shown in the cell.
But when I press "Enter" in this cell again the old value is shown instead of New value.
Please help me to understand how can I save changes after editing the cell?
Example 12-12 Adding Map Data to the Table
import java.util.HashMap;
import java.util.Map;
import javafx.application.Application;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.geometry.Insets;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.control.TableCell;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.control.cell.MapValueFactory;
import javafx.scene.control.cell.TextFieldTableCell;
import javafx.scene.layout.VBox;
import javafx.scene.text.Font;
import javafx.stage.Stage;
import javafx.util.Callback;
import javafx.util.StringConverter;
public class TableViewSample extends Application {
public static final String Column1MapKey = "A";
public static final String Column2MapKey = "B";
public static void main(String[] args) {
launch(args);
}
#Override
public void start(Stage stage) {
Scene scene = new Scene(new Group());
stage.setTitle("Table View Sample");
stage.setWidth(300);
stage.setHeight(500);
final Label label = new Label("Student IDs");
label.setFont(new Font("Arial", 20));
TableColumn<Map, String> firstDataColumn = new TableColumn<>("Class A");
TableColumn<Map, String> secondDataColumn = new TableColumn<>("Class B");
firstDataColumn.setCellValueFactory(new MapValueFactory(Column1MapKey));
firstDataColumn.setMinWidth(130);
secondDataColumn.setCellValueFactory(new MapValueFactory(Column2MapKey));
secondDataColumn.setMinWidth(130);
TableView table_view = new TableView<>(generateDataInMap());
table_view.setEditable(true);
table_view.getSelectionModel().setCellSelectionEnabled(true);
table_view.getColumns().setAll(firstDataColumn, secondDataColumn);
Callback<TableColumn<Map, String>, TableCell<Map, String>>
cellFactoryForMap = new Callback<TableColumn<Map, String>,
TableCell<Map, String>>() {
#Override
public TableCell call(TableColumn p) {
return new TextFieldTableCell(new StringConverter() {
#Override
public String toString(Object t) {
return t.toString();
}
#Override
public Object fromString(String string) {
return string;
}
});
}
};
firstDataColumn.setCellFactory(cellFactoryForMap);
secondDataColumn.setCellFactory(cellFactoryForMap);
final VBox vbox = new VBox();
vbox.setSpacing(5);
vbox.setPadding(new Insets(10, 0, 0, 10));
vbox.getChildren().addAll(label, table_view);
((Group) scene.getRoot()).getChildren().addAll(vbox);
stage.setScene(scene);
stage.show();
}
private ObservableList<Map> generateDataInMap() {
int max = 10;
ObservableList<Map> allData = FXCollections.observableArrayList();
for (int i = 1; i < max; i++) {
Map<String, String> dataRow = new HashMap<>();
String value1 = "A" + i;
String value2 = "B" + i;
dataRow.put(Column1MapKey, value1);
dataRow.put(Column2MapKey, value2);
allData.add(dataRow);
}
return allData;
}
}
You need to define the cellEditEvent with setOnEditCommit:
firstDataColumn.setOnEditCommit((CellEditEvent<Map<String, String>, String> t) -> {
((Map<String, String>) t.getTableView().getItems().get(t.getTablePosition().getRow())).put(Column1MapKey, t.getNewValue());
});
I have one a jfree chart which I can generate everytime I run the code.
Now i want to override few more spider graphs on the same chart. please help me how to do that
Above this i need to add one more spider chart using jfree.
Here is my code for doing this chart.
package com.rectrix.exide.pdfbox;
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.GradientPaint;
import java.awt.Paint;
import java.awt.PaintContext;
import java.awt.Rectangle;
import java.awt.RenderingHints;
import java.awt.geom.AffineTransform;
import java.awt.geom.Rectangle2D;
import java.awt.image.ColorModel;
import javax.swing.JPanel;
import org.jfree.chart.ChartPanel;
import org.jfree.chart.ChartUtilities;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.axis.NumberAxis;
import org.jfree.chart.labels.StandardCategoryToolTipGenerator;
import org.jfree.chart.plot.SpiderWebPlot;
import org.jfree.chart.title.LegendTitle;
import org.jfree.chart.title.TextTitle;
import org.jfree.data.category.CategoryDataset;
import org.jfree.data.category.DefaultCategoryDataset;
import org.jfree.ui.*;
public class DemoChart extends ApplicationFrame {
public DemoChart(String s)
{
super(s);
JPanel jpanel = createDemoPanel();
jpanel.setPreferredSize(new Dimension(500, 270));
setContentPane(jpanel);
}
private static CategoryDataset createDataset()
{
String s1 = "First";
String s2 = "Second";
String s3 = "Third";
String s4 = "Forth";
String s5 = "Fivth";
String s6 = "Sixth";
String s7 = "Seventh";
String s8 = "Eighth";
String s9 = "Ninth";
String s10 = "Tenth";
DefaultCategoryDataset defaultcategorydataset = new DefaultCategoryDataset();
int count = 5;
int value = 0;
//String keyRow="s";
for (int i=1;i<=10;i++){
value = i*4;
Comparable colKey = 0;
String keyRow = "s"+i;
for(int j=1;j<=count;j++){
colKey = j;
defaultcategorydataset.addValue(value, keyRow, colKey);
}
}
return defaultcategorydataset;
}
public static JFreeChart createChart1(CategoryDataset categorydataset,double d) {
SpiderWebPlot plot = new SpiderWebPlot(categorydataset);
Color bckColor1 = Color.decode("#4282CE"); //Light blue
Paint p = new GradientPaint(0, 1, bckColor1, 0, 1, bckColor1);
plot.setSeriesPaint(p);
JFreeChart chart = new JFreeChart("", plot);
return chart;
}
public static JPanel createDemoPanel()
{
JFreeChart jfreechart = createChart1(createDataset(), 10D);
return new ChartPanel(jfreechart);
}
public static void main(String args[])
{
DemoChart spiderwebchartdemo1 = new DemoChart("JFreeChart: SpiderWebChartDemo1.java");
spiderwebchartdemo1.pack();
RefineryUtilities.centerFrameOnScreen(spiderwebchartdemo1);
spiderwebchartdemo1.setVisible(true);
}
}
Please help me as soon as possible i need to send this build by tomorrow
Thank u in advance for helping and taking efforts to see this.
I want to override few more spider graphs on the same chart.
It may help to examine how a spider web plot is used to display multivariate data. The simplified example below compares just two OBSERVATIONS, each having five VARIABLES named A .. E, with random values in the range 1 .. 3. By chance, the values for variable B coincide; the rest differ. You can adjust the value of OBSERVATIONS to see the effect, but the result becomes progressively more muddled as the number of observations grows. You may want to alter series visibility, as suggested here, or consider these alternatives.
import java.awt.EventQueue;
import java.util.Random;
import javax.swing.JPanel;
import org.jfree.chart.ChartPanel;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.plot.SpiderWebPlot;
import org.jfree.data.category.CategoryDataset;
import org.jfree.data.category.DefaultCategoryDataset;
import org.jfree.ui.ApplicationFrame;
/** #see https://stackoverflow.com/a/32885067/230513 */
public class SpiderChart extends ApplicationFrame {
private static final int OBSERVATIONS = 2;
private static final int VARIABLES = 5;
private static final Random r = new Random();
public SpiderChart(String s) {
super(s);
add(createDemoPanel());
}
private static CategoryDataset createDataset() {
DefaultCategoryDataset dataset = new DefaultCategoryDataset();
for (int i = 1; i <= OBSERVATIONS; i++) {
String rowKey = "Observation " + i;
for (int j = 1; j <= VARIABLES; j++) {
Comparable colKey = Character.valueOf((char)(j+64));
dataset.addValue(r.nextInt(3) + 1, rowKey, colKey);
}
}
return dataset;
}
public static JFreeChart createChart(CategoryDataset dataset) {
SpiderWebPlot plot = new SpiderWebPlot(dataset);
JFreeChart chart = new JFreeChart("Test", plot);
return chart;
}
public static JPanel createDemoPanel() {
JFreeChart jfreechart = createChart(createDataset());
return new ChartPanel(jfreechart);
}
public static void main(String args[]) {
EventQueue.invokeLater(() -> {
SpiderChart demo = new SpiderChart("SpiderWebChart");
demo.pack();
demo.setDefaultCloseOperation(EXIT_ON_CLOSE);
demo.setVisible(true);
});
}
}