-1

I have a window written in fxml with a TableView and a few TableColumns and other stuff. I am trying to create a function in the controller to this window, that enables the user to select which columns to display via a set of checkboxes on a separate window. This Window would be a child window of the HealthCheckTab. It would have a button that once pressed would get the state of all Checkboxes and would invoke a function in HealthcheckTab that updates the Tableview making the unwanted columns not visible.

This is the window with the TableView (Extract)

                        </TitledPane>
                        <TitledPane fx:id="classificationNumbers" animated="false"
                            text="HealthCheck Classification Numbers">
                            <content>
                                <ScrollPane fitToHeight="true" fitToWidth="true"
                                    hbarPolicy="ALWAYS" maxHeight="1.7976931348623157E308"
                                    maxWidth="1.7976931348623157E308" pannable="true">
                                    <content>
                                        <TableView fx:id="HcTable" editable="true"
                                            maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308"
                                            minWidth="-Infinity" tableMenuButtonVisible="true">
                                            <columns>
                                                <TableColumn fx:id="colId" editable="false"
                                                    maxWidth="-Infinity" minWidth="40.0" prefWidth="-1.0" text="ID" />
                                                <TableColumn fx:id="colName" editable="false"
                                                    maxWidth="1.7976931348623157E308" minWidth="60.0"
                                                    prefWidth="-1.0" text="Name" />
                                                <TableColumn fx:id="colVal" maxWidth="1.7976931348623157E308"
                                                    minWidth="55.0" prefWidth="-1.0" text="Value" />
                                                <TableColumn fx:id="colDescrCn" editable="false"
                                                    maxWidth="1.7976931348623157E308" minWidth="90.0"
                                                    prefWidth="-1.0" text="Comment (CN)" />
                                                <TableColumn fx:id="colDatatype" editable="false"
                                                    maxWidth="1.7976931348623157E308" minWidth="80.0"
                                                    prefWidth="-1.0" text="Datatype" />
                                                <TableColumn fx:id="colTool" maxWidth="1.7976931348623157E308"
                                                    minWidth="50.0" prefWidth="-1.0" text="Tool" visible="false" />
                                                <TableColumn fx:id="colPrio" editable="false"
                                                    maxWidth="1.7976931348623157E308" minWidth="60.0"
                                                    prefWidth="-1.0" text="Priority" />
                                                <TableColumn fx:id="colScope" maxWidth="1.7976931348623157E308"
                                                    minWidth="50.0" prefWidth="-1.0" text="Scope" visible="false" />
                                                <TableColumn fx:id="colAvg" editable="false"
                                                    maxWidth="1.7976931348623157E308" minWidth="50.0"
                                                    prefWidth="-1.0" text="AVG" visible="false" />
                                                <TableColumn fx:id="colMin" maxWidth="1.7976931348623157E308"
                                                    minWidth="50.0" prefWidth="-1.0" text="MIN" visible="false" />
                                                <TableColumn fx:id="colRelComp" prefWidth="122.0"
                                                    text="Relative Comparable" />
                                            </columns>
                                        </TableView>
                                    </content>
                                </ScrollPane>
                            </content>
                        </TitledPane>
                    

This is the controller (Extract)

    @FXML
    private TreeView<String> HCTree;
    @FXML
    private TableView<Map> HcTable;

    @FXML
    private TableColumn<Map, String> colId;
    @FXML
    private TableColumn<Map, String> colName;
    @FXML
    private TableColumn<Map, String> colVal;
    @FXML
    private TableColumn<Map, String> colDescrCn;
    @FXML
    private TableColumn<Map, String> colDatatype;
    @FXML
    private TableColumn<Map, String> colTool;
    @FXML
    private TableColumn<Map, String> colPrio;
    @FXML
    private TableColumn<Map, String> colScope;
    @FXML
    private TableColumn<Map, String> colAvg;
    @FXML
    private TableColumn<Map, String> colMin;
    @FXML
    private TableColumn<Map, String> colRelComp;



    // -----------------------------------------------------------------------------------------------
    // REFRESH TABLE
    // -----------------------------------------------------------------------------------------------

    public void refreshTable() {
        System.out.println("apply");
        colScope.setVisible(true);
        //colId.setVisible(false);
    

    }

Separate window (Extract)

@FXML
    private void handleApplyViewOptions() {
        try {
            FXMLLoader loader = new FXMLLoader(getClass().getResource("HealthCheckTab.fxml"));
            Stage stage = new Stage(StageStyle.DECORATED);
            stage.setScene(new Scene(loader.load()));
            HealthCheckTabController controller = loader.<HealthCheckTabController> getController();
            controller.refreshTable();
        } catch (IOException e) {
            java.lang.System.err.println(e.getStackTrace());
        }
        Stage stage = (Stage) btnApply.getScene().getWindow();
        stage.close();
    }

The refreshTable function does not hide the Scope Column at all. I don't know why...

Jason Aller
  • 3,541
  • 28
  • 38
  • 38
  • 1. The "scope" column appears to have index 7, not 8. (why not just call `colScope.setVisible(...)` anyway) 2. You're expecting that calling `setVisible(true)` will hide something? 3. Where are you calling `refreshTable()`? I recommend you create a [MCVE] that demonstrates the problem, and post that, instead of posting an incomplete part of your project (which has a lot of code that is not relevant to the problem). – James_D Jun 22 '17 at 15:33
  • yes I was expecting setVisible(true) to change something, what am I missing/doing wrong? I left out the unnecessary parts and added the lines where refresh is invoked... – Pietro Pozzoli Jun 22 '17 at 15:44
  • Surely if you want to *hide* something you would use `setVisible(false)`???? – James_D Jun 22 '17 at 15:45
  • In your `handleApplyViewOptions` method, I don't see where you ever show the new stage you create. – James_D Jun 22 '17 at 15:46
  • Again, all this would be so much easier to diagnose (either for you, or for others), if you would write a specific (i.e. new) application that just tried to do the part you are having trouble with. Simply posting snippets from a larger project is not much help. – James_D Jun 22 '17 at 15:48
  • in that case colScope is initialised as not visible: `` and I would be expecting it to somehow appear... – Pietro Pozzoli Jun 22 '17 at 15:48
  • OK, I see that now. It sort of contradicts the title of your question... :). Where are you showing the new stage you create in `handleApplyViewOptions()`? If you don't show the stage, you won't see the changes you made to it. – James_D Jun 22 '17 at 15:49
  • right, if I show the stage it opens a new Window with the correct view, I want to update the old one instead; this is my first fx-project, I am sorry if my question is trivial... How do I change this: `Stage stage = new Stage(StageStyle.DECORATED);` into the stage the input to open my Window that invokes the refresh function comes from? – Pietro Pozzoli Jun 22 '17 at 15:54
  • I'm confused. If the view is already showing, why are you loading the FXML file again? Write a [MCVE] and post that, instead of the code you have posted. – James_D Jun 22 '17 at 15:56

1 Answers1

3

You are loading a new copy of the UI defined in HealthCheckTab.fxml and calling refreshTable on the controller for that UI (which is never displayed).

Probably an easier approach for this is to register an onHidden handler with the dialog you create, and call refreshTable when the dialog is hidden.

Here is a SSCCE:

Main.fxml:

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

<?import javafx.scene.layout.BorderPane?>
<?import javafx.scene.control.TableView?>
<?import javafx.scene.control.TableColumn?>
<?import javafx.scene.layout.HBox?>
<?import javafx.scene.control.Button?>
<?import javafx.geometry.Insets?>

<BorderPane fx:controller="MainController" xmlns:fx="http://javafx.com/fxml/1">
    <center>
        <TableView >
            <columns>
                <TableColumn fx:id="nameColumn" text="Name" />
                <TableColumn fx:id="optionalColumn" text="Data" />
            </columns>
        </TableView>
    </center>
    <bottom>
        <HBox alignment="CENTER">
            <Button text="Configure View" onAction="#showViewOptions" />
            <padding>
                <Insets top="5" left="5" bottom="5" right="5"/>
            </padding>
        </HBox>
    </bottom>
</BorderPane>

MainController.java:

import java.io.IOException;

import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.control.TableColumn;
import javafx.stage.Stage;

public class MainController {

    @FXML
    private TableColumn<Void, Void> nameColumn ;
    @FXML
    private TableColumn<Void, Void> optionalColumn ;

    @FXML
    private void showViewOptions() throws IOException {
        FXMLLoader loader = new FXMLLoader(ViewOptionsController.class.getResource("ViewOptions.fxml"));
        Parent root = loader.load();
        ViewOptionsController controller = loader.getController();
        controller.setOptionalColumnVisible(optionalColumn.isVisible());
        Scene scene = new Scene(root);
        Stage stage = new Stage();
        stage.setScene(scene);
        stage.initOwner(nameColumn.getTableView().getScene().getWindow());
        stage.setOnHidden(e -> {
            refreshTable(controller.isOptionalColumnVisible());
        });
        stage.show();
    }

    private void refreshTable(boolean showOptionalColumn) {
        optionalColumn.setVisible(showOptionalColumn);
    }
}

ViewOptions.fxml:

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

<?import javafx.scene.layout.VBox?>
<?import javafx.scene.control.CheckBox?>
<?import javafx.scene.control.Button?>
<?import javafx.geometry.Insets?>

<VBox fx:controller="ViewOptionsController" spacing="5" alignment="center" xmlns:fx="http://javafx.com/fxml/1">
    <CheckBox text="Show Data Column" fx:id="optionalColumnVisibleCheckBox" />
    <Button text="OK" onAction="#close" />
    <padding>
        <Insets top="5" left="5" right="5" bottom="5"/>
    </padding>
</VBox>

ViewOptionsController.java:

import javafx.beans.property.BooleanProperty;
import javafx.fxml.FXML;
import javafx.scene.control.CheckBox;

public class ViewOptionsController {

    @FXML
    private CheckBox optionalColumnVisibleCheckBox ;

    public BooleanProperty optionalColumnVisibleProperty() {
        return optionalColumnVisibleCheckBox.selectedProperty();
    }

    public final boolean isOptionalColumnVisible() {
        return optionalColumnVisibleProperty().get();
    }

    public final void setOptionalColumnVisible(boolean optionalColumnVisible) {
        optionalColumnVisibleProperty().set(optionalColumnVisible);
    }

    @FXML
    private void close() {
        optionalColumnVisibleCheckBox.getScene().getWindow().hide();
    }
}

Application class:

import java.io.IOException;

import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;

public class HideColumnsFromDialog extends Application {

    @Override
    public void start(Stage primaryStage) throws IOException {
        Parent root = FXMLLoader.load(MainController.class.getResource("Main.fxml"));
        Scene scene = new Scene(root, 600, 600);
        primaryStage.setScene(scene);
        primaryStage.show();
    }

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

As an aside, note that the functionality you are implementing here is built in to the table view already: you can use

<TableView fx:id="HcTable" tableMenuButtonVisible="true" ... >

and the table will show a button that shows a drop-down menu, from which the user can choose which columns are visible.

James_D
  • 201,275
  • 16
  • 291
  • 322