setVisible () не скрывает узел - PullRequest
0 голосов
/ 02 ноября 2018

У меня есть LineChart с 4 различными сериями. Есть флажки, которые должны показывать / скрывать соответствующие серии из графика. Но когда я нажимал чекбоксы для «Euler», «Improved Euler», «Runge-Kutta», они вообще не влияют на график, пока я не нажму чекбокс «Exact». Абсолютно не могу решить проблему.

Вот как я пытаюсь скрыть / показать:

@FXML private NumberAxis xAxis = new NumberAxis();
@FXML private NumberAxis yAxis = new NumberAxis();
@FXML private LineChart<Number, Number> chartAll = new LineChart<>(xAxis, yAxis);

private XYChart.Series<Number, Number> exactSeries = new XYChart.Series<>();
private XYChart.Series<Number, Number> eulerSeries= new XYChart.Series<>();
private XYChart.Series<Number, Number> improvedEulerSeries = new XYChart.Series<>();
private XYChart.Series<Number, Number> rungeKuttaSeries = new XYChart.Series<>();

@FXML private CheckBox exactChartCheckbox;
@FXML private CheckBox eulerChartCheckbox;
@FXML private CheckBox improvedEulerChartCheckbox;
@FXML private CheckBox rungeKuttaChartCheckbox;

@FXML
protected void handlePlotButton(ActionEvent event) {
    chartAll.getData().clear();
    double x0 = Double.parseDouble(x0Input.getText());
    double y0 = Double.parseDouble(y0Input.getText());
    double x = Double.parseDouble(xInput.getText());
    double step = Double.parseDouble(stepInput.getText());
    IVP ivpForExact = new IVP(x0, y0, x, step);
    Exact exact = new Exact(ivpForExact);
    Euler euler = new Euler(ivpForExact);
    ImprovedEuler improvedEuler = new ImprovedEuler(ivpForExact);
    RungeKutta rungeKutta = new RungeKutta(ivpForExact);
    exactSeries.setName("Exact");
    eulerSeries.setName("Euler");
    improvedEulerSeries.setName("Improved Euler");
    rungeKuttaSeries.setName("Runge-Kutta");
    for (int i = 0; i < exact.getGrid().getSize(); i++) {
        exactSeries.getData().add(new XYChart.Data<>(exact.getGrid().getXat(i), exact.getGrid().getYat(i)));
        eulerSeries.getData().add(new XYChart.Data<>(euler.getGrid().getXat(i), euler.getGrid().getYat(i)));
        improvedEulerSeries.getData().add(new XYChart.Data<>(improvedEuler.getGrid().getXat(i), improvedEuler.getGrid().getYat(i)));
        rungeKuttaSeries.getData().add(new XYChart.Data<>(rungeKutta.getGrid().getXat(i), rungeKutta.getGrid().getYat(i)));
    }
    chartAll.getData().add(exactSeries);
    chartAll.getData().add(eulerSeries);
    chartAll.getData().add(improvedEulerSeries);
    chartAll.getData().add(rungeKuttaSeries);
    stepInput.clear();
    }

@FXML
protected void exactChartCheckboxPressed(ActionEvent event) {
    if(!exactChartCheckbox.isSelected()) {
        chartAll.getData().get(0).getNode().setVisible(false);
    } else {
        chartAll.getData().get(0).getNode().setVisible(true);
    }
}

@FXML
protected void eulerChartCheckboxPressed(ActionEvent event) {
    if(!eulerChartCheckbox.isSelected()) {
        chartAll.getData().get(1).getNode().setVisible(false);
    } else {
        chartAll.getData().get(1).getNode().setVisible(true);
    }
}

Вот FXML:

<?xml version="1.0" encoding="UTF-8"?>

<?import javafx.geometry.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.chart.*?>
<?import javafx.scene.layout.*?>

<GridPane fx:id="scene" alignment="center" hgap="10" vgap="10" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="sample.Controller">
    <columnConstraints>
        <ColumnConstraints />
    </columnConstraints>
    <rowConstraints>
        <RowConstraints />
    </rowConstraints>
    <children>
        <Pane fx:id="pane" prefHeight="600.0" prefWidth="1080.0">
            <children>
                <LineChart fx:id="chartAll" createSymbols="false" layoutX="48.0" layoutY="135.0" prefHeight="427.0" prefWidth="698.0">
                    <xAxis>
                        <NumberAxis label="x" fx:id="xAxis" />
                    </xAxis>
                    <yAxis>
                        <NumberAxis fx:id="yAxis" autoRanging="false" label="y" lowerBound="-10.0" upperBound="40.0" />
                    </yAxis>
               <opaqueInsets>
                  <Insets />
               </opaqueInsets>
                </LineChart>
                <Button layoutX="48.0" layoutY="54.0" mnemonicParsing="false" prefHeight="41.0" prefWidth="120.0" text="Solutions" />
                <TextField layoutX="883.0" layoutY="211.0" prefHeight="25.0" prefWidth="96.0" text="0" fx:id="x0Input" />
                <TextField fx:id="y0Input" layoutX="883.0" layoutY="254.0" prefHeight="25.0" prefWidth="96.0" text="3" />
                <TextField layoutX="883.0" layoutY="296.0" prefHeight="25.0" prefWidth="96.0" text="5.5" fx:id="xInput" />
                <TextField fx:id="stepInput" layoutX="883.0" layoutY="336.0" prefHeight="25.0" prefWidth="96.0" text="0.1" />
                <Label layoutX="841.0" layoutY="215.0" text="x0" />
                <Label layoutX="841.0" layoutY="258.0" text="y0" />
                <Label layoutX="841.0" layoutY="300.0" text="X" />
                <Label layoutX="835.0" layoutY="340.0" text="step" />
                <Button fx:id="plotButton" layoutX="896.0" layoutY="385.0" mnemonicParsing="false" onAction="#handlePlotButton" prefHeight="41.0" prefWidth="71.0" text="Plot" />
            <CheckBox fx:id="exactChartCheckbox" layoutX="347.0" layoutY="562.0" mnemonicParsing="false" onAction="#exactChartCheckboxPressed" selected="true" text="Exact" />
            <CheckBox fx:id="improvedEulerChartCheckbox" layoutX="523.0" layoutY="562.0" mnemonicParsing="false" onAction="#improvedEulerChartCheckboxPressed" selected="true" text="Improved Euler" />
            <CheckBox fx:id="rungeKuttaChartCheckbox" layoutX="646.0" layoutY="562.0" mnemonicParsing="false" onAction="#rungeKuttaChartCheckboxPressed" selected="true" text="Runge-Kutta" />
            <CheckBox fx:id="eulerChartCheckbox" layoutX="444.0" layoutY="562.0" mnemonicParsing="false" onAction="#eulerChartCheckboxPressed" selected="true" text="Euler" />
            </children>
        </Pane>
    </children>
</GridPane>

Вот результат

после того, как я прячу сначала «Эйлера», а затем «Точного»:
after I hide firstly

после того, как я показываю «Точный», затем «Эйлер»:
after I show

Проблема на самом деле в том, что график обновляется только тогда, когда я отмечаю / снимаю флажок «Точное», все три других не влияют на график. Но когда я нажимаю флажок «Точный», они также пытаются обновиться, но делают это неправильно.

Ответы [ 3 ]

0 голосов
/ 03 ноября 2018

Кажется, это зависит от вашей удачи или какого-то устаревшего кода JavaFX. Когда я изменил каждую серию на Массив серии:

private ArrayList<XYChart.Series<Number, Number>> exactSeries = new ArrayList<>();
private ArrayList<XYChart.Series<Number, Number>> eulerSeries = new ArrayList<>();
private ArrayList<XYChart.Series<Number, Number>> improvedEulerSeries = new ArrayList<>();
private ArrayList<XYChart.Series<Number, Number>> rungeKuttaSeries = new ArrayList<>();

, а затем создайте общую функцию для всех случаев:

private void turnVisibility(CheckBox checkBox, ArrayList<XYChart.Series<Number, Number>> seriesList) {
    if (!checkBox.isSelected()) {
        for(XYChart.Series<Number, Number> series: seriesList) {
            series.getNode().setVisible(false);
        }
    } else {
        for(XYChart.Series<Number, Number> series: seriesList) {
            series.getNode().setVisible(true);
        }
    }
}

Видимость начинает работать правильно.

0 голосов
/ 03 ноября 2018

Чтобы эффективно скрыть узел, попробуйте установить управляемое свойство

series.getNode().setManaged(false);

Определяет, будет ли компоновка этого узла управляться его родителем. Если узел управляется, его родительский объект будет учитывать геометрию узла в своих собственных предпочтительных вычислениях размера и layoutBounds и будет размещать ее во время этапа компоновки сцены. При изменении layoutBounds управляемого узла он автоматически запускает ретрансляцию графа сцены до ближайшего корневого макета (который обычно является корневым узлом сцены).

Если узел неуправляемый, его родительский объект будет игнорировать дочерний элемент как в вычислениях предпочтительного размера, так и в макете. Изменения в layoutBounds не будут вызывать ретрансляцию выше него. Если неуправляемый узел имеет тип Parent, он будет действовать как «корень макета», что означает, что вызов Parent.requestLayout () под ним будет вызывать ретрансляцию только ветви, укорененной узлом, тем самым изолируя изменения макета в этом. корень и ниже. Приложение должно установить размер и положение неуправляемого узла.

0 голосов
/ 02 ноября 2018

Исходя из длины моего комментария, я публикую его в ответе, а не в комментарии.

Во-первых, если вы проверяете документацию узла в XYChart.Series

Узел для отображения для этой серии. Это создается диаграммой, если он использует узлы для представления всей серии. Например, график использует это для линии, но точечная диаграмма не использует это. Этот узел будет установлен, как только серия будет добавлена ​​в график. Вы можете тогда получить его, чтобы добавить слушателей мыши и т.д.

Из вышесказанного ясно, что вы можете легко положиться на узел, если это линейный график. И по вашему скриншоту видно, что вы уже используете LineChart. Что не проблема. Если вы проверяете тип узла, он будет иметь тип Path. Но все становится немного грязно, если на вашем линейном графике отображаются точки данных. Иногда переключение видимости узла (пути) само по себе не может привести к желаемому поведению. Например, проверьте снимок экрана ниже.

enter image description here

Поэтому, чтобы скрыть серию из диаграммы, я бы порекомендовал добавить / удалить серию из данных , а не переключать видимость узла ряда.

Возвращаясь к вашей проблеме, я быстро проверил переключение видимости линий, и оно отлично работает для всех серий. Может быть, проблема в вашем коде. Как упомянул @Slaw, Минимальный, Полный и Проверяемый пример может помочь нам понять проблему или даже решить вашу проблему самостоятельно.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...