1

The below code plot a graph which values can be plotted by inputting values into a Spinner. I've added choice boxes next to these spinners, and I'd like it where I change the values of the choicebox so the axis labels change according to the choice boxes

public class ScatterAdd extends Application {
    private final XYSeries series = new XYSeries("Voltage");

    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) {
        domainLabels.getItems().addAll("Current", "Seconds");
        domainLabels.setValue("Current");

        rangeLabels.getItems().addAll("Voltage", "Metres");
        rangeLabels.setValue("Voltage");

        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);
        });
        
        var xSpin = new Spinner<Double>(-10000.000, 10000.000, 0);
        xSpin.setEditable(true);
        xSpin.setPromptText("Xvalue");

        var ySpin = new Spinner<Double>(-10000.000, 10000.000, 0);
        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);
        BorderPane.setAlignment(enter, Pos.CENTER);
        
        BorderPane root = new BorderPane();
        root.setCenter(new ChartViewer(createChart()));
        root.setBottom(enter);

        stage.setTitle("ScatterAdd");
        stage.setScene(new Scene(root, 640, 480));
        stage.show();

    }

    public static void main(String[] args) {
        launch(args);
    }

}

Ive attempted to do this my self by adding a condition in the createchart method however i could'nt get this to work.

  • 2
    I kind of get nervous when I see `import java.awt.*` in a JavaFX app. I know you are using JFreeChart, so perhaps you need some awt classes, even though JFreeChart can work with a JavaFX bridge (I don't need if you actually need awt classes for this or not). If you do need awt classes, I recommend fully qualifying their names at usage sites rather than globally importing the awt library. There are numerous awt classes and JavaFX classes that have the same unqualified name. Without qualification, the code becomes error-prone and hard to understand. – jewelsea Oct 25 '22 at 19:09
  • 1
    I strongly endorse @jewelsea's recommendation; nothing from `java.awt.*` is required in this case, but there are a number of potential collisions between type names in [tag:jfreechart] and [tag:javafx]; also, use `equals()` to compare strings. – trashgod Oct 25 '22 at 22:41
  • I've removed the unnecessary import statements especially java.awt thanks – armitageshanks99 Oct 26 '22 at 08:39

1 Answers1

2

As shown here, a ChoiceBox<T> can listen to its selection model and respond to changes. As shown here, such a listener can alter the appearance of a chart's components as required.

Given a pair of ChoiceBox<String> instances, the selection listeners update the axis labels as shown in the image below:

ChoiceBox<String> domainLabels = new ChoiceBox<>();
ChoiceBox<String> rangeLabels = new ChoiceBox<>();
…
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);
});

Axis label image

trashgod
  • 203,806
  • 29
  • 246
  • 1,045
  • I've amended my code with this however still the axis labels won't change according to the choicebox is there any other code I have to alter outside of the createchart method. thanks – armitageshanks99 Oct 26 '22 at 08:58
  • Be sure to initialize the boxes' items; if you have problems, please [edit] your question to include your revised [mre]. – trashgod Oct 26 '22 at 16:57
  • I've edited my question with the code i added to the createchart method. – armitageshanks99 Oct 26 '22 at 20:46
  • You're invoking `createChart()` _each time_ the listener is called; instead, create the listeners _after_ the chart is created in `start()`. – trashgod Oct 26 '22 at 22:23
  • I've edited my question with the code inside the start() method but I still get the same issue where the labels don't change when the choiceboxes are selected. – armitageshanks99 Oct 27 '22 at 09:50
  • You're invoking `createChart()` _again_ when you instantiate `ChartViewer`; instead, pass the existing instance: `new ChartViewer(chart)`. – trashgod Oct 27 '22 at 12:18
  • I've changed the instance to chart instead of createchart and it works now thank you – armitageshanks99 Oct 27 '22 at 13:19