發現DragEvent發生在哪個TableColumn(在TableView中)的最佳方法是什麼?JavaFX - 檢測並突出顯示正在拖動的TableColumn
我希望能夠突出顯示(例如,將背景顏色更改爲黃色,或者在列的周圍顯示黃色邊框)作爲拖動項的TableColumn將其懸停在其上方,以便清除它給用戶他們正在放哪一列。當拖動完成後,我將不得不確保TableView的樣式被恢復。
要清楚,確切的細胞被丟棄並不重要 - 只是列。
發現DragEvent發生在哪個TableColumn(在TableView中)的最佳方法是什麼?JavaFX - 檢測並突出顯示正在拖動的TableColumn
我希望能夠突出顯示(例如,將背景顏色更改爲黃色,或者在列的周圍顯示黃色邊框)作爲拖動項的TableColumn將其懸停在其上方,以便清除它給用戶他們正在放哪一列。當拖動完成後,我將不得不確保TableView的樣式被恢復。
要清楚,確切的細胞被丟棄並不重要 - 只是列。
要做到這一點,您需要註冊拖動監聽器與每個單元格,使單元格拖動時列更新其樣式。我會用ObjectProperty
這樣做來表示當前的「放置目標列」(即拖動正在發生的列),並且觀察它並從單元中更新它。要訪問這些單元,您需要一個單元工廠。
以下方法會將這種支持添加到列中。它還尊重在預先連接的細胞工廠定義的任何功能:
private <S,T> void configureDropTargetColumn(TableColumn<S,T> column, ObjectProperty<TableColumn<?,?>> dropTarget) {
Callback<TableColumn<S,T>, TableCell<S,T>> currentCellFactory = column.getCellFactory() ;
column.setCellFactory(tc -> {
TableCell<S,T> cell = currentCellFactory.call(tc);
dropTarget.addListener((obs, oldColumn, newColumn) ->
cell.pseudoClassStateChanged(PseudoClass.getPseudoClass("drop-target"), newColumn==column));
cell.setOnDragEntered(e -> dropTarget.set(column));
cell.setOnDragExited(e -> dropTarget.set(null));
return cell ;
});
}
下面是使用通常的「接觸表」示例的SSCCE:
import java.util.Arrays;
import java.util.List;
import java.util.function.Function;
import javafx.application.Application;
import javafx.beans.property.ObjectProperty;
import javafx.beans.property.SimpleObjectProperty;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
import javafx.beans.value.ObservableValue;
import javafx.css.PseudoClass;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.control.TableCell;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.input.ClipboardContent;
import javafx.scene.input.Dragboard;
import javafx.scene.input.TransferMode;
import javafx.scene.layout.BorderPane;
import javafx.stage.Stage;
import javafx.util.Callback;
public class TableColumnDropTargetExample extends Application {
@Override
public void start(Stage primaryStage) {
TableView<Person> table = new TableView<>();
table.getColumns().add(column("First Name", Person::firstNameProperty));
table.getColumns().add(column("Last Name", Person::lastNameProperty));
table.getColumns().add(column("Email", Person::emailProperty));
ObjectProperty<TableColumn<?,?>> dropTargetColumn = new SimpleObjectProperty<>();
table.getColumns().forEach(col -> configureDropTargetColumn(col, dropTargetColumn));
table.getItems().addAll(createData());
Label label = new Label("Drag me");
label.getStyleClass().add("drag-source");
label.setOnDragDetected(e -> {
Dragboard db = label.startDragAndDrop(TransferMode.COPY_OR_MOVE);
ClipboardContent cc = new ClipboardContent();
cc.putString(label.getText());
db.setContent(cc);
});
label.setOnDragDone(e -> dropTargetColumn.set(null));
BorderPane root = new BorderPane(table);
root.setTop(label);
BorderPane.setAlignment(label, Pos.CENTER);
Scene scene = new Scene(root, 800, 600);
scene.getStylesheets().add("style.css");
primaryStage.setScene(scene);
primaryStage.show();
}
private <S,T> void configureDropTargetColumn(TableColumn<S,T> column, ObjectProperty<TableColumn<?,?>> dropTarget) {
Callback<TableColumn<S,T>, TableCell<S,T>> currentCellFactory = column.getCellFactory() ;
column.setCellFactory(tc -> {
TableCell<S,T> cell = currentCellFactory.call(tc);
dropTarget.addListener((obs, oldColumn, newColumn) ->
cell.pseudoClassStateChanged(PseudoClass.getPseudoClass("drop-target"), newColumn==column));
cell.setOnDragEntered(e -> dropTarget.set(column));
cell.setOnDragExited(e -> dropTarget.set(null));
return cell ;
});
}
private static <S,T> TableColumn<S,T> column(String text, Function<S, ObservableValue<T>> property) {
TableColumn<S,T> col = new TableColumn<>(text);
col.setCellValueFactory(cellData -> property.apply(cellData.getValue()));
return col ;
}
private List<Person> createData() {
return Arrays.asList(
new Person("Jacob", "Smith", "[email protected]"),
new Person("Isabella", "Johnson", "[email protected]"),
new Person("Ethan", "Williams", "[email protected]"),
new Person("Emma", "Jones", "[email protected]"),
new Person("Michael", "Brown", "[email protected]")
);
}
public static class Person {
private final StringProperty firstName = new SimpleStringProperty();
private final StringProperty lastName = new SimpleStringProperty();
private final StringProperty email = new SimpleStringProperty();
public Person(String firstName, String lastName, String email) {
setFirstName(firstName);
setLastName(lastName);
setEmail(email);
}
public final StringProperty firstNameProperty() {
return this.firstName;
}
public final String getFirstName() {
return this.firstNameProperty().get();
}
public final void setFirstName(final String firstName) {
this.firstNameProperty().set(firstName);
}
public final StringProperty lastNameProperty() {
return this.lastName;
}
public final String getLastName() {
return this.lastNameProperty().get();
}
public final void setLastName(final String lastName) {
this.lastNameProperty().set(lastName);
}
public final StringProperty emailProperty() {
return this.email;
}
public final String getEmail() {
return this.emailProperty().get();
}
public final void setEmail(final String email) {
this.emailProperty().set(email);
}
}
public static void main(String[] args) {
launch(args);
}
}
和樣式表:
.table-cell:drop-target {
-fx-background-color: -fx-background ;
-fx-background: yellow ;
-fx-border-color: -fx-table-cell-border-color -fx-table-cell-border-color transparent transparent ;
}
.drag-source {
-fx-font-size: 18 ;
-fx-padding: 10 ;
}
我想獲得拖動的列,使用此代碼,但有些東西不適合我,我改變了以下代碼:'cell.setOnDragEntered( e - > System.out.println(「Entered」)); \t \t \t cell.setOnDragExited(e - > System.out.println(「Exited」));'如果事件被觸發,但沒有顯示任何信息,所以我不能設置dropTarget。 – Sunflame
即使你只對列有興趣,而不是真正的單元格,你需要使用單元工廠在單元格中註冊拖動處理程序。 –
所有的細胞?這不是一個巨大的處理程序列表嗎? – User
除非您的用戶擁有絕對巨大的屏幕,否則每列不可能有超過20或30個單元。我不明白你爲什麼認爲會導致任何問題;處理程序非常輕便。 (如果你真的爲時代廣場上的顯示器編碼,或者類似的東西,你可能需要處理更多緊迫的性能問題......) –