有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java如何修复滚动时的TableView

我是JavaFX的新手,不知道如何解决这个问题。因此,我在TableView中有一个复选框列。例如,我先选择3个框,然后向下滚动表格。但当我转到表的顶部时,复选框不会被选中。 下面是一些代码:

import javafx.application.Application;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.*;
import javafx.scene.control.cell.PropertyValueFactory;
import javafx.scene.layout.BorderPane;
import javafx.stage.Stage;
import javafx.util.Callback;
import java.util.LinkedList;
import java.util.List;

public class App extends Application
{
List<User> list = new LinkedList<>();
TableColumn<User, Integer> id;
TableColumn<User, String> firstName;
TableColumn<User, Boolean> selected;
TableView<User> tableView;

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

@Override
public void start(Stage stage) throws Exception
{
    stage.setHeight(500);
    stage.setWidth(500);
    stage.setMinHeight(200);
    stage.setMinHeight(100);
    stage.setTitle("Table view");

    tableView = new TableView<>();

    ObservableList<User> list = FXCollections.observableArrayList();
    for(int i = 0; i < 40; i++)
    {
        list.add(new User(i, "first name", "last name"));
    }

    id = new TableColumn("ID");
    id.setCellValueFactory(new PropertyValueFactory<User, Integer>("id"));

    firstName = new TableColumn("First Name");
    firstName.setCellValueFactory(new PropertyValueFactory<User, String>("firstName"));

    TableColumn<User, String> lastName = new TableColumn("Last Name");
    lastName.setCellValueFactory(new PropertyValueFactory<User, String>("lastName"));

    selected = new TableColumn("Select");

    Callback<TableColumn<User, Boolean>, TableCell<User, Boolean>> booleanCellFactory =     new Callback<TableColumn<User, Boolean>, TableCell<User, Boolean>>()
    {
        @Override
        public TableCell<User, Boolean> call(TableColumn<User, Boolean> p)
        {
            return new CheckBoxCell();
        }
    };
    selected.setCellValueFactory(new PropertyValueFactory<User, Boolean>("active"));
    selected.setCellFactory(booleanCellFactory);

    tableView.getColumns().addAll(id, firstName, lastName, selected);
    tableView.setItems(list);

    BorderPane pane = new BorderPane();
    pane.setCenter(tableView);

    Scene scene = new Scene(pane);
    stage.setScene(scene);
    stage.show();
}

class CheckBoxCell extends TableCell<User, Boolean>
{
    private CheckBox checkbox;

    @Override
    protected void updateItem(Boolean item, boolean empty)
    {
        super.updateItem(item, empty);
        checkbox = new CheckBox();
        checkbox.setAlignment(Pos.CENTER);
        setAlignment(Pos.CENTER);
        setGraphic(checkbox);
        checkbox.setOnAction(new EventHandler<ActionEvent>()
        {
            @Override
            public void handle(ActionEvent actionEvent)
            {

                if(!checkbox.isSelected())
                {
                    list.remove(tableView.getItems().get(getTableRow().getIndex()));
                } else
                {
                    list.add(tableView.getItems().get(getTableRow().getIndex()));
                }
                System.out.println(list);
            }
        });
    }
}
}    

以及数据类“用户”:

public class User
{
private int id;
private String firstName;
private String lastName;

User(int id, String firstName, String lastName)
{
    this.id = id;
    this.firstName = firstName;
    this.lastName = lastName;
}

public int getId()
{
    return id;
}

public void setId(int id)
{
    this.id = id;
}

public String getFirstName()
{
    return firstName;
}

public void setFirstName(String firstName)
{
    this.firstName = firstName;
}

public String getLastName()
{
    return lastName;
}

public void setLastName(String lastName)
{
    this.lastName = lastName;
}

}

共 (2) 个答案

  1. # 1 楼答案

    在表列“slected”的代码中

    selected.setCellValueFactory(new PropertyValueFactory<User, Boolean>("active"));
    

    您正在将propertyvalue工厂设置为“active”,但用户类中没有“active”属性。当您移动滚动条tableview时,触发updateItem方法,因为您没有活动属性(即使您的属性默认值为false)复选框。(项目1);行将取消选中复选框,因为项目值始终为false

    若要解决此问题,请在用户类中定义一个活动的BooleanProperty,并在用户选中/取消选中复选框时更新属性值

    下面是正在运行的完整代码

    import javafx.application.Application;
    import javafx.collections.FXCollections;
    import javafx.collections.ObservableList;
    import javafx.event.ActionEvent;
    import javafx.event.EventHandler;
    import javafx.geometry.Pos;
    import javafx.scene.Scene;
    import javafx.scene.control.*;
    import javafx.scene.control.cell.PropertyValueFactory;
    import javafx.stage.Stage;
    import javafx.util.Callback;
    import javafx.scene.layout.BorderPane;
    import java.util.LinkedList;
    import java.util.List;
    
    public class TestApp extends Application {
    
            List<User> list = new LinkedList<>();
            TableColumn<User, Integer> id;
            TableColumn<User, String> firstName;
            TableColumn<User, Boolean> selected;
            TableView<User> tableView;
    
    public static void main(String[] args)
            {
            launch();
            }
    
    @Override
    public void start(Stage stage) throws Exception
            {
            stage.setHeight(500);
            stage.setWidth(500);
            stage.setMinHeight(200);
            stage.setMinHeight(100);
            stage.setTitle("Table view");
    
            tableView = new TableView<>();
    
            ObservableList<User> list = FXCollections.observableArrayList();
            for(int i = 0; i < 40; i++)
            {
            list.add(new User(i, "first name", "last name"));
            }
    
            id = new TableColumn("ID");
            id.setCellValueFactory(new PropertyValueFactory<User, Integer>("id"));
    
            firstName = new TableColumn("First Name");
            firstName.setCellValueFactory(new PropertyValueFactory<User, String>("firstName"));
    
            TableColumn<User, String> lastName = new TableColumn("Last Name");
            lastName.setCellValueFactory(new PropertyValueFactory<User, String>("lastName"));
    
            selected = new TableColumn("Select");
    
            Callback<TableColumn<User, Boolean>, TableCell<User, Boolean>> booleanCellFactory =     new Callback<TableColumn<User, Boolean>, TableCell<User, Boolean>>()
            {
    @Override
    public TableCell<User, Boolean> call(TableColumn<User, Boolean> p)
            {
            return new CheckBoxCell();
            }
            };
            selected.setCellValueFactory(new PropertyValueFactory<User, Boolean>("active"));
            selected.setCellFactory(booleanCellFactory);
    
            tableView.getColumns().addAll(id, firstName, lastName, selected);
            tableView.setItems(list);
    
            BorderPane pane = new BorderPane();
            pane.setCenter(tableView);
    
            Scene scene = new Scene(pane);
            stage.setScene(scene);
            stage.show();
           }
    
    class CheckBoxCell extends TableCell<User, Boolean>
    {
        private CheckBox checkbox = new CheckBox();
        public CheckBoxCell(){
            checkbox.setOnAction(new EventHandler<ActionEvent>()
            {
                @Override
                public void handle(ActionEvent actionEvent)
                {
    
                    if(!checkbox.isSelected())
                    {
                        list.remove(tableView.getItems().get(getTableRow().getIndex()));
                        User user = getTableView().getItems().get(getTableRow().getIndex());
                        user.setActive(false);
                    } else
                    {
                        list.add(tableView.getItems().get(getTableRow().getIndex()));
                        User user = getTableView().getItems().get(getTableRow().getIndex());
                        user.setActive(true);
                    }
                    System.out.println(list);
                }
            });
        }
    
        @Override
        protected void updateItem(Boolean item, boolean empty)
        {
            super.updateItem(item, empty);
           if(!empty && item != null) {
               checkbox.setAlignment(Pos.CENTER);
               checkbox.setSelected(item);
               setAlignment(Pos.CENTER);
               setGraphic(checkbox);
           }
        }
    }
    

    用户类别:

    public class User
    {
        private IntegerProperty id;
        private StringProperty firstName;
        private StringProperty lastName;
        private BooleanProperty active;
    
        User(int id, String firstName, String lastName)
        {
            this.id = new SimpleIntegerProperty(id);
            this.firstName = new SimpleStringProperty(firstName);
            this.lastName = new SimpleStringProperty(lastName);
            this.active = new SimpleBooleanProperty(false);
        }
    
        public int getId() {
            return id.get();
        }
    
        public IntegerProperty idProperty() {
            return id;
        }
    
        public void setId(int id) {
            this.id.set(id);
        }
    
        public String getFirstName() {
            return firstName.get();
        }
    
        public StringProperty firstNameProperty() {
            return firstName;
        }
    
        public void setFirstName(String firstName) {
            this.firstName.set(firstName);
        }
    
        public String getLastName() {
            return lastName.get();
        }
    
        public StringProperty lastNameProperty() {
            return lastName;
        }
    
        public void setLastName(String lastName) {
            this.lastName.set(lastName);
        }
    
        public boolean getActive() {
            return active.get();
        }
    
        public BooleanProperty activeProperty() {
            return active;
        }
    
        public void setActive(boolean active) {
            this.active.set(active);
        }
    }
    
  2. # 2 楼答案

    有很多问题

    首先,TableCell实例将被重用。您需要将CheckBox的值设置为item的值

    @Override
    protected void updateItem(Boolean item, boolean empty)
    {
        super.updateItem(item, empty);
        checkbox = new CheckBox();
    
        if(!empty && item != null)
            checkbox.setSelected(item);
    
        ....
    
      }
    

    其次,您有两个名为list的变量。TableView没有绑定到顶部声明的List<User>,这可能就是您的行没有删除自己的原因

    您应该替换此行:

    List<User> list = new LinkedList<>();
    

    为此:

    ObservableList<User> list = FXCollections.observableArrayList();
    

    最后,您应该为您的数据对象使用JavaFX属性,使用TableView(无需使用反射来访问值)它们将执行得更快,并且将提供更好的JavaFX控件处理

    You can learn about the properties on the Oracle website.