FXML,JavaFX 8,TableView:在每行中创建一个删除按钮,并相应地删除该行 [英] FXML, JavaFX 8, TableView: Make a delete button in each row and delete the row accordingly

查看:122
本文介绍了FXML,JavaFX 8,TableView:在每行中创建一个删除按钮,并相应地删除该行的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用TableView(FXML),在其中我希望所有行的最后一列都带有删除按钮.

以下视频显示了我的意思: TableView中的YouTube删除按钮

这是我的主控制器类中的内容:

public Button del() {
    Button del = new Button();
    del.setText("X");
    del.setPrefWidth(30);
    del.setOnAction(new EventHandler<ActionEvent>() {
        public void handle(ActionEvent event) {
            int i = index.get();
            if(i > -1) {
                goals.remove(i);
                list.getSelectionModel().clearSelection();
            }
        }
    });
    return del;
}

private SimpleIntegerProperty index = new SimpleIntegerProperty();

@Override
public void initialize(URL location, ResourceBundle resources){
    //DateFormat df = new SimpleDateFormat("dd MMM yyyy");
    sdate.setValue(LocalDate.now());
    edate.setValue(LocalDate.now());

    seq.setCellValueFactory(new PropertyValueFactory<Goals, Integer>("id"));
    gol.setCellValueFactory(new PropertyValueFactory<Goals, String>("goal"));
    sdt.setCellValueFactory(new PropertyValueFactory<Goals, Date>("sdte"));
    edt.setCellValueFactory(new PropertyValueFactory<Goals, Date>("edte"));
    prog.setCellValueFactory(new PropertyValueFactory<Goals, Integer>("pb"));
    del.setCellValueFactory(new PropertyValueFactory<Goals, Button>("x"));

    list.setItems(goals);
    list.getSelectionModel().selectedItemProperty().addListener(new ChangeListener<Object>() {
        @Override
        public void changed(ObservableValue<?> observable,
                Object oldValue, Object newValue) {
            index.set(goals.indexOf(newValue));
            System.out.println("Index is: "+goals.indexOf(newValue));
        }

    });
}

每次启动应用程序时,我都会尝试从随机行中单击删除按钮,但它始终会删除第一行.我猜我用于列表的addListener方法未正确实现,并且每次初始化时indexOf(newValue)始终为0.

但是,如果我先单击一行然后单击删除"按钮,它将起作用.但这不是我想要的.我希望用户在不选择某行的情况下按Delete键就可以删除任何行.

感谢您的帮助!

解决方案

您需要为包含删除按钮的列定义一个自定义单元格工厂.

TableColumn<Person, Person> unfriendCol = new TableColumn<>("Anti-social");
unfriendCol.setCellValueFactory(
    param -> new ReadOnlyObjectWrapper<>(param.getValue())
);
unfriendCol.setCellFactory(param -> new TableCell<Person, Person>() {
    private final Button deleteButton = new Button("Unfriend");

    @Override
    protected void updateItem(Person person, boolean empty) {
        super.updateItem(person, empty);

        if (person == null) {
            setGraphic(null);
            return;
        }

        setGraphic(deleteButton);
        deleteButton.setOnAction(
            event -> getTableView().getItems().remove(person)
        );
    }
});

这是一个示例应用程序.它不使用FXML,但是您可以对其进行调整以使其很容易地与FXML一起使用.只需单击反社交"列中的取消好友"按钮即可删除好友.这样做很多,您很快就会筋疲力尽.

import javafx.application.Application;
import javafx.beans.property.ReadOnlyObjectWrapper;
import javafx.beans.property.SimpleStringProperty;
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.Priority;
import javafx.scene.layout.VBox;
import javafx.scene.text.Font;
import javafx.stage.Stage;

public class GestureEvents extends Application {
    private TableView<Person> table = new TableView<>();
    private final ObservableList<Person> data =
        FXCollections.observableArrayList(
            new Person("Jacob", "Smith"),
            new Person("Isabella", "Johnson"),
            new Person("Ethan", "Williams"),
            new Person("Emma", "Jones"),
            new Person("Michael", "Brown")
        );

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

    @Override
    public void start(Stage stage) {
        final Label label = new Label("Friends");
        label.setFont(new Font("Arial", 20));

        final Label actionTaken = new Label();

        TableColumn<Person, Person> unfriendCol = new TableColumn<>("Anti-social");
        unfriendCol.setMinWidth(40);
        unfriendCol.setCellValueFactory(param -> new ReadOnlyObjectWrapper<>(param.getValue()));
        unfriendCol.setCellFactory(param -> new TableCell<Person, Person>() {
            private final Button deleteButton = new Button("Unfriend");

            @Override
            protected void updateItem(Person person, boolean empty) {
                super.updateItem(person, empty);

                if (person == null) {
                    setGraphic(null);
                    return;
                }

                setGraphic(deleteButton);
                deleteButton.setOnAction(event -> data.remove(person));
            }
        });

        TableColumn<Person, String> firstNameCol = new TableColumn<>("First Name");
        firstNameCol.setMinWidth(100);
        firstNameCol.setCellValueFactory(
                new PropertyValueFactory<>("firstName"));

        TableColumn<Person, String> lastNameCol = new TableColumn<>("Last Name");
        lastNameCol.setMinWidth(100);
        lastNameCol.setCellValueFactory(
                new PropertyValueFactory<>("lastName"));

        table.setItems(data);
        table.getColumns().addAll(unfriendCol, firstNameCol, lastNameCol);
        table.setPrefHeight(250);

        final VBox vbox = new VBox();
        vbox.setSpacing(5);
        vbox.setPadding(new Insets(10, 10, 10, 10));
        vbox.getChildren().addAll(label, table, actionTaken);
        VBox.setVgrow(table, Priority.ALWAYS);

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

    public static class Person {

        private final SimpleStringProperty firstName;
        private final SimpleStringProperty lastName;

        private Person(String fName, String lName) {
            this.firstName = new SimpleStringProperty(fName);
            this.lastName = new SimpleStringProperty(lName);
        }

        public String getFirstName() {
            return firstName.get();
        }

        public void setFirstName(String fName) {
            firstName.set(fName);
        }

        public String getLastName() {
            return lastName.get();
        }

        public void setLastName(String fName) {
            lastName.set(fName);
        }
    }
}

I am working on a TableView (FXML) where I want to have all the rows accompanied with a delete button at the last column.

Here's a video that shows what I mean: YouTube Delete Button in TableView

Here's what I have in my main controller class:

public Button del() {
    Button del = new Button();
    del.setText("X");
    del.setPrefWidth(30);
    del.setOnAction(new EventHandler<ActionEvent>() {
        public void handle(ActionEvent event) {
            int i = index.get();
            if(i > -1) {
                goals.remove(i);
                list.getSelectionModel().clearSelection();
            }
        }
    });
    return del;
}

private SimpleIntegerProperty index = new SimpleIntegerProperty();

@Override
public void initialize(URL location, ResourceBundle resources){
    //DateFormat df = new SimpleDateFormat("dd MMM yyyy");
    sdate.setValue(LocalDate.now());
    edate.setValue(LocalDate.now());

    seq.setCellValueFactory(new PropertyValueFactory<Goals, Integer>("id"));
    gol.setCellValueFactory(new PropertyValueFactory<Goals, String>("goal"));
    sdt.setCellValueFactory(new PropertyValueFactory<Goals, Date>("sdte"));
    edt.setCellValueFactory(new PropertyValueFactory<Goals, Date>("edte"));
    prog.setCellValueFactory(new PropertyValueFactory<Goals, Integer>("pb"));
    del.setCellValueFactory(new PropertyValueFactory<Goals, Button>("x"));

    list.setItems(goals);
    list.getSelectionModel().selectedItemProperty().addListener(new ChangeListener<Object>() {
        @Override
        public void changed(ObservableValue<?> observable,
                Object oldValue, Object newValue) {
            index.set(goals.indexOf(newValue));
            System.out.println("Index is: "+goals.indexOf(newValue));
        }

    });
}

Each time I launch the application, I will try to click the delete button from random rows but it always delete the first row. I guess the addListener method I use for list is not properly implemented and indexOf(newValue) is always 0 at every initialisation.

However, it will work if I click a row first and then click the delete button. But this is not what I want. I want users to be able to delete any row if they press the delete button without selecting the row.

Appreciate your help guys!

解决方案

You need a custom cell factory defined for the column containing the delete button.

TableColumn<Person, Person> unfriendCol = new TableColumn<>("Anti-social");
unfriendCol.setCellValueFactory(
    param -> new ReadOnlyObjectWrapper<>(param.getValue())
);
unfriendCol.setCellFactory(param -> new TableCell<Person, Person>() {
    private final Button deleteButton = new Button("Unfriend");

    @Override
    protected void updateItem(Person person, boolean empty) {
        super.updateItem(person, empty);

        if (person == null) {
            setGraphic(null);
            return;
        }

        setGraphic(deleteButton);
        deleteButton.setOnAction(
            event -> getTableView().getItems().remove(person)
        );
    }
});

Here is a sample app. It doesn't use FXML, but you could adapt it to work with FXML very easily. Just click on an "Unfriend" button in the "Anti-social" column to delete a friend. Do it a lot and you will soon run out of friends.

import javafx.application.Application;
import javafx.beans.property.ReadOnlyObjectWrapper;
import javafx.beans.property.SimpleStringProperty;
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.Priority;
import javafx.scene.layout.VBox;
import javafx.scene.text.Font;
import javafx.stage.Stage;

public class GestureEvents extends Application {
    private TableView<Person> table = new TableView<>();
    private final ObservableList<Person> data =
        FXCollections.observableArrayList(
            new Person("Jacob", "Smith"),
            new Person("Isabella", "Johnson"),
            new Person("Ethan", "Williams"),
            new Person("Emma", "Jones"),
            new Person("Michael", "Brown")
        );

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

    @Override
    public void start(Stage stage) {
        final Label label = new Label("Friends");
        label.setFont(new Font("Arial", 20));

        final Label actionTaken = new Label();

        TableColumn<Person, Person> unfriendCol = new TableColumn<>("Anti-social");
        unfriendCol.setMinWidth(40);
        unfriendCol.setCellValueFactory(param -> new ReadOnlyObjectWrapper<>(param.getValue()));
        unfriendCol.setCellFactory(param -> new TableCell<Person, Person>() {
            private final Button deleteButton = new Button("Unfriend");

            @Override
            protected void updateItem(Person person, boolean empty) {
                super.updateItem(person, empty);

                if (person == null) {
                    setGraphic(null);
                    return;
                }

                setGraphic(deleteButton);
                deleteButton.setOnAction(event -> data.remove(person));
            }
        });

        TableColumn<Person, String> firstNameCol = new TableColumn<>("First Name");
        firstNameCol.setMinWidth(100);
        firstNameCol.setCellValueFactory(
                new PropertyValueFactory<>("firstName"));

        TableColumn<Person, String> lastNameCol = new TableColumn<>("Last Name");
        lastNameCol.setMinWidth(100);
        lastNameCol.setCellValueFactory(
                new PropertyValueFactory<>("lastName"));

        table.setItems(data);
        table.getColumns().addAll(unfriendCol, firstNameCol, lastNameCol);
        table.setPrefHeight(250);

        final VBox vbox = new VBox();
        vbox.setSpacing(5);
        vbox.setPadding(new Insets(10, 10, 10, 10));
        vbox.getChildren().addAll(label, table, actionTaken);
        VBox.setVgrow(table, Priority.ALWAYS);

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

    public static class Person {

        private final SimpleStringProperty firstName;
        private final SimpleStringProperty lastName;

        private Person(String fName, String lName) {
            this.firstName = new SimpleStringProperty(fName);
            this.lastName = new SimpleStringProperty(lName);
        }

        public String getFirstName() {
            return firstName.get();
        }

        public void setFirstName(String fName) {
            firstName.set(fName);
        }

        public String getLastName() {
            return lastName.get();
        }

        public void setLastName(String fName) {
            lastName.set(fName);
        }
    }
}

这篇关于FXML,JavaFX 8,TableView:在每行中创建一个删除按钮,并相应地删除该行的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆