How to add a button to a single row in a one column TableView?

Faye :

I have a TableView with a single Column and I want to have a Button in the last row of that TableView/Column. The Button should be disabled until a row is selected and then it should be enabled. I've done numerous searches on this but everything I've found seems to be adding a button to every row within a multi-column table. Is there a quick way to do this?

Here are some sample images:

enter image description here

TableButtonView.fxml:

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

<?import javafx.geometry.Insets?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.ButtonBar?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.control.TableColumn?>
<?import javafx.scene.control.TableView?>
<?import javafx.scene.control.TextField?>
<?import javafx.scene.layout.AnchorPane?>
<?import javafx.scene.layout.HBox?>
<?import javafx.scene.layout.VBox?>
<?import javafx.scene.text.Font?>

<AnchorPane maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308" prefHeight="406.0" prefWidth="200.0" xmlns="http://javafx.com/javafx/8.0.171" xmlns:fx="http://javafx.com/fxml/1" fx:controller="tablebutton.TableButtonController">
   <children>
      <VBox layoutX="60.0" layoutY="22.0" maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308" prefHeight="200.0" prefWidth="100.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
         <children>
            <Label alignment="CENTER" maxWidth="1.7976931348623157E308" prefHeight="51.0" prefWidth="200.0" text="Agency Customization">
               <font>
                  <Font name="System Bold" size="13.0" />
               </font>
            </Label>
            <HBox maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308" prefHeight="40.0">
               <children>
                  <Label alignment="CENTER_RIGHT" maxHeight="1.7976931348623157E308" prefHeight="30.0" prefWidth="70.0" text="Agency:  " />
                  <TextField fx:id="agencyTextField" maxHeight="1.7976931348623157E308" prefHeight="30.0" prefWidth="45.0" />
                  <Button fx:id="addButton" maxHeight="1.7976931348623157E308" onAction="#onAdd" prefHeight="30.0" prefWidth="67.0" text="_Add">
                     <HBox.margin>
                        <Insets left="10.0" />
                     </HBox.margin>
                  </Button>
               </children>
               <padding>
                  <Insets bottom="10.0" />
               </padding>
            </HBox>
            <TableView fx:id="agencyTableView" maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308" prefHeight="276.0">
               <columns>
                  <TableColumn fx:id="agencyColumn" prefWidth="188.0" text="Agency" />
               </columns>
               <VBox.margin>
                  <Insets left="5.0" right="5.0" />
               </VBox.margin>
            </TableView>
            <ButtonBar maxWidth="1.7976931348623157E308">
               <buttons>
                  <Button fx:id="okAgencyButton" mnemonicParsing="false" onAction="#onOK" text="OK" />
                  <Button fx:id="cancelAgencyButton" mnemonicParsing="false" onAction="#onCancel" text="Cancel" />
               </buttons>
               <padding>
                  <Insets bottom="5.0" right="20.0" top="5.0" />
               </padding>
            </ButtonBar>
         </children>
      </VBox>
   </children>
</AnchorPane>

TableButtonController.java:

package tablebutton;

import java.net.URL;
import java.util.ResourceBundle;
import javafx.beans.property.ReadOnlyStringWrapper;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.Button;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.control.TextField;
import javafx.scene.web.WebView;
import javafx.stage.Stage;

public class TableButtonController implements Initializable {

    private WebView helpWebView;
    @FXML
    private TextField agencyTextField;
    @FXML
    private Button addButton;
    @FXML
    private TableView<String> agencyTableView;
    @FXML
    private TableColumn<String, String> agencyColumn;
    @FXML
    private Button okAgencyButton;
    @FXML
    private Button cancelAgencyButton;

    @Override
    public void initialize(URL url, ResourceBundle rb) {
        agencyColumn.setCellValueFactory(cellData -> 
                new ReadOnlyStringWrapper(cellData.getValue())
        );
        agencyColumn.setStyle( "-fx-alignment: CENTER;");

        ObservableList<String> agencies = FXCollections.observableArrayList(
                    "AA","DL","LH");
        agencyTableView.getItems().addAll(agencies);
    }    

    @FXML
    private void onAdd(ActionEvent event) {
    }


    @FXML
    private void onOK(ActionEvent event) {
        // Just exit for now
        Stage stage = (Stage) okAgencyButton.getScene().getWindow();
        stage.close();
    }

    @FXML
    private void onCancel(ActionEvent event) {
        // Just exit for now
        Stage stage = (Stage) cancelAgencyButton.getScene().getWindow();
        stage.close();
    }

}

TableButton.java:

package tablebutton;

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 TableButton extends Application {

    @Override
    public void start(Stage primaryStage) {
        try
        {
            FXMLLoader loader = new FXMLLoader(getClass().getResource("TableButtonView.fxml"));
            Scene scene = new Scene((Parent) loader.load());
            primaryStage.setScene(scene);
            primaryStage.setTitle("TableView Button Test");
            primaryStage.show();
        }
        catch (IOException ignored)
        {
        }
    }

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

Trying to put the button actually inside the TableView is problematic and not recommended. There is a technical difficulty in getting the button to render in the last row of the TableView (this is not trivial), and there are also potential usability issues (what if there are a lot of rows in the table and the table needs to be scrolled, does the remove button just scroll out of view? if so, then how would a user find it if they wanted to remove something).

Instead, don't put the button in the TableView:

  1. Use a VBox which contains the the TableView and the Button.
  2. Set appropriate constraints so that the Button butts right up under the TableView and is sized to the width of the TableView.
  3. Bind the disable property of the Button to an empty selected items set.

Remove not selected Remove selected

Sample code:

import javafx.application.Application;
import javafx.beans.binding.Bindings;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.geometry.Insets;
import javafx.scene.Scene;
import javafx.scene.control.*;
import javafx.scene.control.cell.PropertyValueFactory;
import javafx.scene.layout.VBox;
import javafx.scene.paint.Color;
import javafx.stage.Stage;

public class Remover extends Application {
    @Override
    public void start(Stage stage) throws Exception {
        ObservableList<NamedColor> colors = FXCollections.observableArrayList(
                new NamedColor("red", Color.RED),
                new NamedColor("green", Color.GREEN),
                new NamedColor("blue", Color.BLUE),
                new NamedColor("indigo", Color.INDIGO)
        );

        TableView<NamedColor> table = new TableView<>(colors);
        table.getSelectionModel().setSelectionMode(SelectionMode.MULTIPLE);
        table.setColumnResizePolicy(TableView.CONSTRAINED_RESIZE_POLICY);
        TableColumn<NamedColor, String> colorNames = new TableColumn<>("Colors");
        colorNames.setCellValueFactory(new PropertyValueFactory<>("name"));
        table.getColumns().add(colorNames);

        Button remove = new Button("Remove");
        remove.disableProperty().bind(
                Bindings.isEmpty(
                        table.getSelectionModel().getSelectedItems()
                )
        );
        remove.setMaxWidth(Double.MAX_VALUE);
        remove.setOnAction(event ->
                table.getItems()
                        .removeAll(
                                table.getSelectionModel().getSelectedItems()
                        )
        );

        VBox layout = new VBox(table, remove);
        layout.setPadding(new Insets(10));

        stage.setScene(new Scene(layout));
        stage.show();
    }

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

    public static class NamedColor {
        private String name;
        private Color color;

        public NamedColor(String name, Color color) {
            this.name = name;
            this.color = color;
        }

        public String getName() {
            return name;
        }

        public Color getColor() {
            return color;
        }
    }
}

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=142476&siteId=1