我编写了以下代码,用于链接两个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);
}
}
提前致谢!
答案 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);
}
}