链接JavaFX 8 TableView选项

时间:2016-01-14 00:40:12

标签: java javafx

我编写了以下代码,用于链接两个tableviews之间的选择。我面临的问题是链接只在行的索引上完成而不是匹配单元格内容。

理想情况下,如果在任一表格中选择了“纸张”,我希望两个表格中<name>等于“纸张”的所有行也都突出显示。

有没有简单的&amp;实现这一目标的有效方法?

这是我到目前为止编写的测试代码:

public class TableSelection extends Application {
@SuppressWarnings("unchecked")
@Override
public void start(Stage primaryStage) throws Exception {
    ObservableList<Item> data1 = FXCollections.observableArrayList();
    ObservableList<Item> data2 = FXCollections.observableArrayList();

    String[] names = new String[]{"Wood", "Paper", "Scissors"};

    for (int i = 1; i < 15; i++) {
        Item j = new Item();
        j.setName(names[(int)(Math.random() * names.length)]);
        j.setNn((int)(Math.random() * 100));

        if (i<5) data1.add(j);
        else data2.add(j);
    }

    TableColumn<Item, String> nameCol = new TableColumn<>("Name");
    TableColumn<Item, Integer> nnCol = new TableColumn<>("nn");
    nameCol.setCellValueFactory(new PropertyValueFactory<Item, String>("Name"));
    nnCol.setCellValueFactory(new PropertyValueFactory<Item, Integer>("nn"));

    TableColumn<Item, String> nameCol2 = new TableColumn<>("Name");
    TableColumn<Item, Integer> nnCol2 = new TableColumn<>("nn");
    nameCol2.setCellValueFactory(new PropertyValueFactory<Item, String>("Name"));
    nnCol2.setCellValueFactory(new PropertyValueFactory<Item, Integer>("nn"));

    TableView<Item> table1 = new TableView<>();
    table1.itemsProperty().setValue(data1);     
    table1.getColumns().addAll(nameCol, nnCol);

    TableView<Item> table2 = new TableView<>();
    table2.itemsProperty().setValue(data2);     
    table2.getColumns().addAll(nameCol2, nnCol2);

    table1.setSelectionModel(table2.getSelectionModel());   
    table1.getSelectionModel().setSelectionMode(SelectionMode.MULTIPLE);

    VBox myPane = new VBox();
    myPane.setAlignment(Pos.CENTER);
    myPane.setPadding(new Insets(12));
    myPane.setSpacing(12);
    myPane.setMaxHeight(500);
    myPane.getChildren().addAll(table1, table2);

    Scene myScene = new Scene(myPane);

    primaryStage.setScene(myScene);
    primaryStage.show();
}

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

提前致谢!

2 个答案:

答案 0 :(得分:1)

这是一个快速的解决方案。但请注意,由于在选择单元格(并发)时更改了选择模型,可能会出现同步问题。

import java.util.HashSet;
import java.util.Set;

import javafx.application.Application;
import javafx.beans.value.ChangeListener;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.SelectionMode;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.control.cell.PropertyValueFactory;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;

public class TableSelection extends Application {

    TableView<Item> table1 = new TableView<>();
    TableView<Item> table2 = new TableView<>();

    boolean adapting = false;

    @SuppressWarnings("unchecked")
    @Override
    public void start(Stage primaryStage) throws Exception {
        ObservableList<Item> data1 = FXCollections.observableArrayList();
        ObservableList<Item> data2 = FXCollections.observableArrayList();

        String[] names = new String[] { "Wood", "Paper", "Scissors" };

        for (int i = 1; i < 15; i++) {
            Item j = new Item();
            j.setName(names[(int) (Math.random() * names.length)]);
            j.setNn((int) (Math.random() * 100));

            if (i < 5)
                data1.add(j);
            else
                data2.add(j);
        }

        TableColumn<Item, String> nameCol = new TableColumn<>("Name");
        TableColumn<Item, Integer> nnCol = new TableColumn<>("nn");
        nameCol.setCellValueFactory(new PropertyValueFactory<Item, String>("Name"));
        nnCol.setCellValueFactory(new PropertyValueFactory<Item, Integer>("nn"));

        TableColumn<Item, String> nameCol2 = new TableColumn<>("Name");
        TableColumn<Item, Integer> nnCol2 = new TableColumn<>("nn");
        nameCol2.setCellValueFactory(new PropertyValueFactory<Item, String>("Name"));
        nnCol2.setCellValueFactory(new PropertyValueFactory<Item, Integer>("nn"));

        table1.itemsProperty().setValue(data1);
        table1.getColumns().addAll(nameCol, nnCol);

        table2.itemsProperty().setValue(data2);
        table2.getColumns().addAll(nameCol2, nnCol2);

        // table1.setSelectionModel(table2.getSelectionModel());
        table1.getSelectionModel().setSelectionMode(SelectionMode.MULTIPLE);
        table2.getSelectionModel().setSelectionMode(SelectionMode.MULTIPLE);

        table2.getSelectionModel().selectedItemProperty().addListener((ChangeListener<Item>) (observable, oldValue, newValue) -> {

            if (adapting)
                return;

            try {

                adapting = true;

                selectCurrent(table2);
                selectOthers(table2, table1);

            } finally {
                adapting = false;
            }

        });

        table1.getSelectionModel().selectedItemProperty().addListener((ChangeListener<Item>) (observable, oldValue, newValue) -> {

            if (adapting)
                return;

            try {

                adapting = true;

                selectCurrent(table1);
                selectOthers(table1, table2);

            } finally {
                adapting = false;
            }

        });

        VBox myPane = new VBox();
        myPane.setAlignment(Pos.CENTER);
        myPane.setPadding(new Insets(12));
        myPane.setSpacing(12);
        myPane.setMaxHeight(500);
        myPane.getChildren().addAll(table1, table2);

        Scene myScene = new Scene(myPane);

        primaryStage.setScene(myScene);
        primaryStage.show();
    }

    private void selectCurrent(TableView<Item> currentTableView) {

        Set<String> names = new HashSet<>();

        for (Item item : currentTableView.getSelectionModel().getSelectedItems()) {
            names.add(item.getName());
        }

        for (String name : names) {

            for (Item item : currentTableView.getItems()) {
                if (name.equals(item.getName())) {
                    currentTableView.getSelectionModel().select(item);
                }
            }

        }

    }

    private void selectOthers(TableView<Item> sourceTableView, TableView<Item> targetTableView) {

        Set<String> names = new HashSet<>();

        for (Item item : sourceTableView.getSelectionModel().getSelectedItems()) {
            names.add(item.getName());
        }

        targetTableView.getSelectionModel().clearSelection();

        for (String name : names) {

            for (Item item : targetTableView.getItems()) {
                if (name.equals(item.getName())) {
                    targetTableView.getSelectionModel().select(item);
                }
            }

        }

    }

    public class Item {
        String name;
        int Nn;

        public String getName() {
            return name;
        }

        public void setName(String name) {
            this.name = name;
        }

        public int getNn() {
            return Nn;
        }

        public void setNn(int nn) {
            Nn = nn;
        }

    }

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

您可以统一名称集的创建。您应该为Guard子句使用AtomicBoolean或其他同步方法。我把它留给你。

答案 1 :(得分:0)

根据您的建议,我尝试统一名称选择。由于我在自己的代码中迷失了,所以我将其改为单个选择而不是多个选择。我还尝试了突出显示行的方式,因为我认为可能使用css突出显示可能更有效的targetTableView.getSelectionModel()。select(item)。

名称选择和突出显示都有效但两者都断开连接。我知道突出显示有效,因为我已经初始化了一个值,但是当我选择一个新值时它没有得到更新。

在cellfactory中我还需要做些什么吗?

感谢您的任何建议!

这是完整的代码:

package standAloneTest;

import javafx.application.Application;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.TableCell;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.control.cell.PropertyValueFactory;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;

public class TableSelection extends Application {

    protected String selectedName ="Paper";

    @Override
    public void start(Stage primaryStage) throws Exception {
        ObservableList<Item> data1 = FXCollections.observableArrayList();
        ObservableList<Item> data2 = FXCollections.observableArrayList();

        String[] names = new String[] { "Wood", "Paper", "Scissors" };

        for (int i = 1; i < 15; i++) {
            Item j = new Item();
            j.setName(names[(int) (Math.random() * names.length)]);
            j.setNn((int) (Math.random() * 100));

            if (i < 5)
                data1.add(j);
            else
                data2.add(j);
        }

        TableColumn<Item, String> nameCol = new TableColumn<>("Name");
        TableColumn<Item, Integer> nnCol = new TableColumn<>("nn");
        nameCol.setCellValueFactory(new PropertyValueFactory<Item, String>("Name"));
        nnCol.setCellValueFactory(new PropertyValueFactory<Item, Integer>("nn"));
        //nameCol.setCellFactory();

        TableColumn<Item, String> nameCol2 = new TableColumn<>("Name");
        TableColumn<Item, Integer> nnCol2 = new TableColumn<>("nn");
        nameCol2.setCellValueFactory(new PropertyValueFactory<Item, String>("Name"));

        nameCol2.setCellFactory(column -> {
          return new TableCell<Item, String>() {
              protected void updateItem(String n, boolean empty){
                  super.updateItem(n, empty);
                  System.out.println("string : " + n);
                  if (n == null || empty) {
                        setText(null);
                        setStyle("");
                  } else {
                      setText(n);

                      // Style if selected value
                      if (n.equals(selectedName) ){
                          setStyle("-fx-background-color: yellow");
                      }
                  }
             }    
          };
        });

        nnCol2.setCellValueFactory(new PropertyValueFactory<Item, Integer>("nn"));


        TableView<Item> table1 = new TableView<>();
        table1.itemsProperty().setValue(data1);
        table1.getColumns().addAll(nameCol, nnCol);

        TableView<Item> table2 = new TableView<>();
        table2.itemsProperty().setValue(data2);
        table2.getColumns().addAll(nameCol2, nnCol2);

        // table1.setSelectionModel(table2.getSelectionModel());
        table1.getSelectionModel().selectedItemProperty().addListener(new ChangeListener<Item>() {
            @Override
            public void changed(ObservableValue<? extends Item> observable, Item oldValue, Item newValue) {
                selectedName = newValue.getName().toString();
                System.out.println(selectedName);
            }
        });

        table2.getSelectionModel().selectedItemProperty().addListener(new ChangeListener<Item>() {
            @Override
            public void changed(ObservableValue<? extends Item> observable, Item oldValue, Item newValue) {
                selectedName = newValue.getName().toString();
                System.out.println(selectedName);
            }
        });



        VBox myPane = new VBox();
        myPane.setAlignment(Pos.CENTER);
        myPane.setPadding(new Insets(12));
        myPane.setSpacing(12);
        myPane.setMaxHeight(500);
        myPane.getChildren().addAll(table1, table2);

        Scene myScene = new Scene(myPane);

        primaryStage.setScene(myScene);
        primaryStage.show();
    }

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