Djalil lounis
Djalil lounis

Reputation: 121

Add a button to a cells in a TableView (JAVAFX)

i am trying to add an edit Button to my table. when i click the button it will open a window with the item selected,I tried several approaches to add the button but no one works for me. thank you here is the code of my controller:

public class AmdinConsolcontroler implements Initializable{



@FXML
// here we add the create new user window the the event butto
private void ActionCreateNewUser (ActionEvent evt)
{
    try {
  Parent root =     FXMLLoader.load(SimpleFXapp.class.getResource("/Views/CreateUser.fxml"));
  Stage primaryStage = new Stage();
  Scene Scene = new Scene(root);
  primaryStage.setScene(Scene);
  primaryStage.setTitle("Create");
  primaryStage.show();
      }
  catch(Exception Err)
  {
   System.out.println("exception from create user");
  }
}

      // Creating the Observable list to be data for the table  
     ObservableList<Users> data1 =     FXCollections.observableList(Users.GetShortedUsrs());
    // Declaring the Table 
   @FXML
    TableView<Users> ShortedUserList;
   //Declaring the Columns of the atble  
   @FXML
   TableColumn<Users, String> ColFirstname ;
   @FXML 
   TableColumn<Users, String>LastName;
   @FXML 
   TableColumn<Users, String>UserName;
  @FXML 
  TableColumn<Users, String>Role;
 @FXML 
 TableColumn<Users, String>IsActive;
 @FXML 
 TableColumn<Users, String>LastLogin;
@FXML
TableColumn Edit = new TableColumn<>("Edit");


// Addin the edit button 




@Override
public void initialize(URL url, ResourceBundle rb) 
{
    try{
        // initialzing the table column
        ColFirstname.setCellValueFactory(new PropertyValueFactory("UserName"));
        LastName.setCellValueFactory(new PropertyValueFactory("UserLastname"));
        UserName.setCellValueFactory(new PropertyValueFactory("LoginId"));
        Role.setCellValueFactory(new PropertyValueFactory("UserRole"));
        IsActive.setCellValueFactory(new PropertyValueFactory("IsActive"));
        LastLogin.setCellValueFactory(new PropertyValueFactory("LastLogin"));
       // Adding the edit Button to the 



       // setng data  the table         
        ShortedUserList.setItems(data1);
       }
  catch(Exception Err)
      { 
          System.out.println(Err.getMessage());
        }










}  




}

Upvotes: 2

Views: 11775

Answers (2)

James_D
James_D

Reputation: 209684

Here is an alternative solution in which the cell value property for the edit column is a ReadOnlyObjectWrapper which wraps the entire "row object". Then it sets a cellFactory on the column to display the button. Since the item property of the cell represents the whole row, the value for the row can easily be accessed using cell.getItem().

import java.util.function.Function;

import javafx.application.Application;
import javafx.beans.property.ReadOnlyObjectWrapper;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
import javafx.beans.value.ObservableValue;
import javafx.geometry.HPos;
import javafx.geometry.Insets;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.TableCell;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.control.TextField;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.ColumnConstraints;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.Priority;
import javafx.stage.Modality;
import javafx.stage.Stage;
import javafx.stage.StageStyle;

public class TableViewWithEditButton extends Application {

    @Override
    public void start(Stage primaryStage) {
        TableView<Person> table = new TableView<>();
        table.getColumns().add(column("First Name", Person::firstNameProperty, 150));
        table.getColumns().add(column("Last Name", Person::lastNameProperty, 150));
        table.getColumns().add(column("Email", Person::emailProperty, 200));

        TableColumn<Person, Person> editColumn = column("Edit", ReadOnlyObjectWrapper<Person>::new, 60);

        table.getColumns().add(editColumn);

        editColumn.setCellFactory(col -> {
            Button editButton = new Button("Edit");
            TableCell<Person, Person> cell = new TableCell<Person, Person>() {
                @Override
                public void updateItem(Person person, boolean empty) {
                    super.updateItem(person, empty);
                    if (empty) {
                        setGraphic(null);
                    } else {
                        setGraphic(editButton);
                    }
                }
            };

            editButton.setOnAction(e -> edit(cell.getItem(), primaryStage));

            return cell ;
        });

        table.getItems().addAll(
                new Person("Jacob", "Smith", "[email protected]"),
                new Person("Isabella", "Johnson", "[email protected]"),
                new Person("Ethan", "Williams", "[email protected]"),
                new Person("Emma", "Jones", "[email protected]"),
                new Person("Michael", "Brown", "[email protected]")
        );

        primaryStage.setScene(new Scene(new BorderPane(table)));
        primaryStage.show();
    }

    private void edit(Person person, Stage primaryStage) {
        TextField firstNameTextField = boundTF(person.firstNameProperty());
        TextField lastNameTextField = boundTF(person.lastNameProperty());
        TextField emailTextField = boundTF(person.emailProperty());

        GridPane grid = new GridPane();
        grid.setHgap(10);
        grid.setVgap(10);
        grid.setPadding(new Insets(16));


        grid.addRow(0, new Label("First name:"), firstNameTextField);
        grid.addRow(1, new Label("Last name:"), lastNameTextField);
        grid.addRow(2, new Label("Email:"), emailTextField);

        Button okButton = new Button("OK");

        grid.add(okButton, 0, 3, 2, 1);

        ColumnConstraints leftCol = new ColumnConstraints();
        leftCol.setHgrow(Priority.NEVER);
        leftCol.setHalignment(HPos.RIGHT);
        ColumnConstraints rightCol = new ColumnConstraints();
        rightCol.setHgrow(Priority.SOMETIMES);
        grid.getColumnConstraints().addAll(leftCol, rightCol);
        GridPane.setHalignment(okButton, HPos.CENTER);

        Scene scene = new Scene(grid);
        Stage stage = new Stage();

        okButton.setOnAction(e -> stage.hide());
        firstNameTextField.setOnAction(e -> stage.hide());
        lastNameTextField.setOnAction(e -> stage.hide());
        emailTextField.setOnAction(e -> stage.hide());

        stage.initModality(Modality.APPLICATION_MODAL);
        stage.initOwner(primaryStage);
        stage.initStyle(StageStyle.UNDECORATED);
        stage.setScene(scene);
        stage.show();
    }

    private TextField boundTF(StringProperty binding) {
        TextField textField = new TextField();
        textField.textProperty().bindBidirectional(binding);
        textField.setMinWidth(80);
        return textField ;
    }

    private <S,T> TableColumn<S,T> column(String title, Function<S, ObservableValue<T>> property, double width) {
        TableColumn<S,T> col = new TableColumn<>(title);
        col.setCellValueFactory(cellData -> property.apply(cellData.getValue()));
        col.setPrefWidth(width);
        return col ;
    }

    public static class Person {
        private final StringProperty firstName = new SimpleStringProperty();
        private final StringProperty lastName = new SimpleStringProperty();
        private final StringProperty email = new SimpleStringProperty();

        public Person(String firstName, String lastName, String email) {
            setFirstName(firstName);
            setLastName(lastName);
            setEmail(email);
        }

        public final StringProperty firstNameProperty() {
            return this.firstName;
        }

        public final java.lang.String getFirstName() {
            return this.firstNameProperty().get();
        }

        public final void setFirstName(final java.lang.String firstName) {
            this.firstNameProperty().set(firstName);
        }

        public final StringProperty lastNameProperty() {
            return this.lastName;
        }

        public final java.lang.String getLastName() {
            return this.lastNameProperty().get();
        }

        public final void setLastName(final java.lang.String lastName) {
            this.lastNameProperty().set(lastName);
        }

        public final StringProperty emailProperty() {
            return this.email;
        }

        public final java.lang.String getEmail() {
            return this.emailProperty().get();
        }

        public final void setEmail(final java.lang.String email) {
            this.emailProperty().set(email);
        }


    }

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

Upvotes: 5

clartaq
clartaq

Reputation: 5372

Here's one way you can do it.

package tablebuttoncolumndemo;

import javafx.application.Application;
import javafx.beans.property.ObjectProperty;
import javafx.beans.property.SimpleObjectProperty;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.scene.Scene;
import javafx.scene.control.Alert;
import javafx.scene.control.Alert.AlertType;
import javafx.scene.control.Button;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.control.cell.PropertyValueFactory;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;

public class TableButtonColumnDemo extends Application {

    @Override
    public void start(Stage primaryStage) {

        ObservableList<EditableFileRow> data = FXCollections.observableArrayList(
                new EditableFileRow("A File"),
                new EditableFileRow("A Big File"),
                new EditableFileRow("A Lost File")
        );

        TableColumn editColumn = new TableColumn("Edit");
        editColumn.setCellValueFactory(new PropertyValueFactory<>("editButton"));
        TableColumn fileNameColumn = new TableColumn("File Name");
        fileNameColumn.setCellValueFactory(new PropertyValueFactory<>("fileName"));
        TableView table = new TableView();
        table.getColumns().addAll(editColumn, fileNameColumn);
        table.setItems(data);

        StackPane root = new StackPane();

        root.getChildren().add(table);

        Scene scene = new Scene(root, 300, 250);

        primaryStage.setTitle("Button Column Demo");
        primaryStage.setScene(scene);

        primaryStage.show();
    }

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

    public static class EditButton extends Button {

        public EditButton(String fileName) {
            super("Edit");
            setOnAction((event) -> {
                Alert alert = new Alert(AlertType.INFORMATION);
                alert.setTitle("Hey!");
                alert.setHeaderText(null);
                alert.setContentText("You're editing \"" + fileName + "\"");
                alert.showAndWait();
            });
        }
    }

    public static class EditableFileRow {

        private final SimpleStringProperty fileName;
        private final SimpleObjectProperty<EditButton> editButton;

        public EditableFileRow(String fileName) {
            this.fileName = new SimpleStringProperty(fileName);
            editButton = new SimpleObjectProperty(new EditButton(fileName));
        }

        public String getFileName() {
            return fileName.get();
        }

        public void setFileName(String fName) {
            fileName.set(fName);
        }

        public StringProperty fileNameProperty() {
            return fileName;
        }

        public EditButton getEditButton() {
            return editButton.get();
        }

        public void setEditButton(EditButton editButton) {
            this.editButton.set(editButton);
        }

        public ObjectProperty<EditButton> editButtonProperty() {
            return editButton;
        }

    }
}

Another way you can try is to put an image instead of a button, with a listener that detects clicks. I often use that method to indicate what type of file it is using different images for pdf's, excel files, text files, and so on.

Upvotes: 2

Related Questions