setVisible()不会隐藏节点

时间:2018-11-01 22:00:21

标签: java javafx

我有4个不同系列的LineChart。有复选框应显示/隐藏图表中的对应系列。但是,当我按下“ Euler”,“ Euler改进”,“ Runge-Kutta”复选框时,它们完全不会影响图表,直到我按下“精确”复选框。绝对不能解决问题。

这是我尝试隐藏/显示的方式:

@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>

这是结果

在我先隐藏“ Euler”然后再隐藏“ Exact”之后:
after I hide firstly "Euler" and then "Exact"

在显示“精确”然后显示“欧拉”之后:
after I show "Exact" then "Euler"

问题实际上是仅当我选中/取消选中“精确”复选框时才会更新图表,所有其他三个都不影响图表。但是,当我按下“精确”复选框时,它们也在尝试进行更新,但操作不正确。

3 个答案:

答案 0 :(得分:1)

要有效隐藏节点,请尝试设置托管属性

series.getNode().setManaged(false);
  

定义此节点的布局是否将由其父节点管理。如果节点是托管节点,则其父节点将把节点的几何形状纳入其自身的首选大小和layoutBounds计算中,并将在场景的布局过程中对其进行布局。如果受管节点的layoutBounds发生更改,它将自动触发将场景图向上中继到最近的布局根(通常是场景的根节点)。

     

如果节点不受管理,则其父节点将在首选大小计算和布局中都忽略子节点。 layoutBounds的更改不会触发其上方的重新布局。如果非托管节点的类型为Parent,则它将充当“布局根”,这意味着对它下面的Parent.requestLayout()的调用将仅中继出该节点根目录下的分支,从而隔离对该布局的更改根及以下。设置非托管节点的大小和位置是应用程序的责任。

答案 1 :(得分:0)

根据评论的时长,我将其发布在答案中而不是评论中。

首先,如果您查看XYChart.Series中的 node 文档,

  

要为此系列显示的节点。这是由图表创建的,如果   它使用节点表示整个系列。例如折线图   使用此线,但散点图不使用它。这个节点   系列一旦添加到图表中,便会设置。那你可以   获取它以添加鼠标侦听器等。

从上面显而易见,如果它是折线图,则可以轻松依赖于节点。从屏幕截图中,我可以看到您已经在使用LineChart。这不是问题。如果检查节点类型,则其类型将为路径。但是如果折线图上显示数据点,情况就会变得有些混乱。有时仅切换节点(路径)的可见性并不能达到预期的效果。例如,检查以下屏幕截图。

enter image description here

因此,要从图表中隐藏系列,我建议从数据中添加/删除系列,而不要切换系列节点的可见性。

谈到您的问题,我进行了快速检查,以切换行的可见性,并且在所有系列中均能正常工作。可能是代码中的一些问题。正如@Slaw所提到的,Minimal, Complete, and Verifiable example可以帮助我们理解问题,甚至可以自己解决问题。

答案 2 :(得分:0)

看来,这取决于您的运气或某些旧版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);
        }
    }
}

可见性开始正常工作。