2017-01-23 37 views
1

發現DragEvent發生在哪個TableColumn(在TableView中)的最佳方法是什麼?JavaFX - 檢測並突出顯示正在拖動的TableColumn

我希望能夠突出顯示(例如,將背景顏色更改爲黃色,或者在列的周圍顯示黃色邊框)作爲拖動項的TableColumn將其懸停在其上方,以便清除它給用戶他們正在放哪一列。當拖動完成後,我將不得不確保TableView的樣式被恢復。

要清楚,確切的細胞被丟棄並不重要 - 只是列。

+0

即使你只對列有興趣,而不是真正的單元格,你需要使用單元工廠在單元格中註冊拖動處理程序。 –

+0

所有的細胞?這不是一個巨大的處理程序列表嗎? – User

+0

除非您的用戶擁有絕對巨大的屏幕,否則每列不可能有超過20或30個單元。我不明白你爲什麼認爲會導致任何問題;處理程序非常輕便。 (如果你真的爲時代廣場上的顯示器編碼,或者類似的東西,你可能需要處理更多緊迫的性能問題......) –

回答

2

要做到這一點,您需要註冊拖動監聽器與每個單元格,使單元格拖動時列更新其樣式。我會用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 ; 
} 
+0

我想獲得拖動的列,使用此代碼,但有些東西不適合我,我改變了以下代碼:'cell.setOnDragEntered( e - > System.out.println(「Entered」)); \t \t \t cell.setOnDragExited(e - > System.out.println(「Exited」));'如果事件被觸發,但沒有顯示任何信息,所以我不能設置dropTarget。 – Sunflame