我在同一个场景中有两个TableView
s密切相关。我想设置一个监听器,当用户在一个表中悬停某一行时,另一个表中具有相同索引的行是" hovered"同样。
我尝试使用自定义行工厂tableView.setRowFactory(...)
解决此问题。在工厂call(...)
方法内部,我可以在目标行上切换CSS伪类(.myclass:hover
),如:
row.hoverProperty().addListener((obs, o, n) -> {
myOtherTable.[get row here].pseudoClassStateChanged(PseudoClass.getPseudoClass("hover"), true);
});
正如您在我的工厂方法中所看到的,我引用了第二个TableView
对象myOtherTable
。我想我必须抓住它的TableRow
对象继续设置伪类,但我无法弄清楚如何。
也许还有更好的方法吗?
答案 0 :(得分:2)
创建一个表示悬停行的索引的属性,以及PseudoClass
:
IntegerProperty hoveredRowIndex = new SimpleIntegerProperty(-1);
PseudoClass appearHovered = PseudoClass.getPseudoClass("appear-hovered");
现在创建一个行工厂,用于创建观察此值及其索引的表行:
Callback<TableView<T>, TableCell<T>> rowFactory = tv -> {
TableRow<T> row = new TableRow<T>() {
private BooleanBinding shouldAppearHovered = Bindings.createBooleanBinding(
() -> getIndex() != -1 && getIndex() == hoveredRowIndex.get(), indexProperty(),
hoveredRowIndex);
{
shouldAppearHovered.addListener(
(obs, wasHovered, isNowHovered) -> pseudoClassStateChanged(appearHovered, isNowHovered));
hoverProperty().addListener((obs, wasHovered, isNowHovered) -> {
if (isNowHovered) {
hoveredRowIndex.set(getIndex());
} else {
hoveredRowIndex.set(-1);
}
});
}
};
return row;
};
(将T
替换为表的实际类型。)
现在使用两个表的行工厂。您可以使用CSS选择器
.table-row-cell:appear-hovered {
/* ... */
}
设置应该显示为悬停的行的样式,或使用
.table-row-cell:appear-hovered .table-cell {
/* ... */
}
为该行中的单个单元格设置样式。
这是一个SSCCE:
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import java.util.function.Function;
import javafx.application.Application;
import javafx.beans.binding.Bindings;
import javafx.beans.binding.BooleanBinding;
import javafx.beans.property.IntegerProperty;
import javafx.beans.property.SimpleIntegerProperty;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
import javafx.beans.value.ObservableValue;
import javafx.css.PseudoClass;
import javafx.geometry.Insets;
import javafx.scene.Scene;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableRow;
import javafx.scene.control.TableView;
import javafx.scene.layout.HBox;
import javafx.stage.Stage;
public class ConnectedHoverTables extends Application {
private IntegerProperty hoveredRowIndex = new SimpleIntegerProperty(-1);
private PseudoClass appearHovered = PseudoClass.getPseudoClass("appear-hovered");
@Override
public void start(Stage primaryStage) {
HBox root = new HBox(10, createTable(), createTable());
root.setPadding(new Insets(20));
Scene scene = new Scene(root);
scene.getStylesheets().add("style.css");
primaryStage.setScene(scene);
primaryStage.show();
}
private TableView<Item> createTable() {
TableView<Item> table = new TableView<>();
table.setRowFactory(tv -> {
TableRow<Item> row = new TableRow<Item>() {
private BooleanBinding shouldAppearHovered = Bindings.createBooleanBinding(
() -> getIndex() != -1 && getIndex() == hoveredRowIndex.get(), indexProperty(),
hoveredRowIndex);
{
shouldAppearHovered.addListener(
(obs, wasHovered, isNowHovered) -> pseudoClassStateChanged(appearHovered, isNowHovered));
hoverProperty().addListener((obs, wasHovered, isNowHovered) -> {
if (isNowHovered) {
hoveredRowIndex.set(getIndex());
} else {
hoveredRowIndex.set(-1);
}
});
}
};
return row;
});
table.setOnMouseClicked(e -> System.gc());
table.getColumns().add(column("Item", Item::nameProperty));
table.getColumns().add(column("Value", Item::valueProperty));
table.getItems().setAll(createData());
return table;
}
private List<Item> createData() {
Random rng = new Random();
List<Item> items = new ArrayList<>();
for (int i = 1; i <= 100; i++) {
Item item = new Item("Item " + i, rng.nextInt(1000));
items.add(item);
}
return items;
}
private <S, T> TableColumn<S, T> column(String title, Function<S, ObservableValue<T>> property) {
TableColumn<S, T> col = new TableColumn<>(title);
col.setCellValueFactory(cellData -> property.apply(cellData.getValue()));
return col;
}
public static class Item {
private final StringProperty name = new SimpleStringProperty();
private final IntegerProperty value = new SimpleIntegerProperty();
public Item(String name, int value) {
setName(name);
setValue(value);
}
public final StringProperty nameProperty() {
return this.name;
}
public final String getName() {
return this.nameProperty().get();
}
public final void setName(final String name) {
this.nameProperty().set(name);
}
public final IntegerProperty valueProperty() {
return this.value;
}
public final int getValue() {
return this.valueProperty().get();
}
public final void setValue(final int value) {
this.valueProperty().set(value);
}
}
public static void main(String[] args) {
launch(args);
}
}
答案 1 :(得分:0)
如果我没记错的话,你无法直接访问TableView的一行。获取行索引的唯一方法是在定义CellFactory时访问属性indexProperty。
我建议您创建一个个性化的扩展TableRow或TableCell对象,您可以在其中存储ID或类似内容......