2017-01-23 3 views
1

Каков наилучший способ узнать, какой TableColumn (в TableView) произошел с помощью DragEvent?JavaFX - Обнаружение и выделение TableColumn перетаскивается на

Я хотел бы выделить (например, изменить цвет фона на желтый или показать желтую рамку вокруг столбца). Столбец Столбец в качестве перетаскиваемого элемента «зависает» над ним, чтобы сделать его понятным для пользователя, на который он падает. Конечно, после завершения перетаскивания мне нужно будет убедиться, что стиль TableView восстановлен.

Чтобы быть ясным, точная ячейка, на которую набрасывается, не имеет значения - только столбец.

+0

Несмотря на то, что вас интересует только столбец, а не фактическая ячейка, вам нужно будет зарегистрировать обработчики перетаскивания с помощью ячеек, используя фабрику ячеек. –

+0

Все ячейки? Разве это не был бы огромный список обработчиков? – User

+0

Если у ваших пользователей нет абсолютно огромного экрана, у вас вряд ли будет более 20 или 30 ячеек на столбе. Я не понимаю, почему вы думаете, что вызовет какие-либо проблемы; обработчики очень легкие. (И если вы действительно кодируете дисплеи на Таймс-сквер или что-то подобное, у вас, вероятно, гораздо более серьезные проблемы с производительностью, чтобы справиться с ...) –

ответ

2

Для этого вам необходимо зарегистрировать прослушиватели перетаскивания с каждой ячейкой, которые заставляют столбцы обновлять свой стиль при перетаскивании ячеек. Я бы сделал это, используя ObjectProperty, чтобы представить текущий столбец «drop target» (т. Е. Столбец, по которому происходит перетаскивание), и как наблюдать, так и обновлять его из ячеек. Чтобы получить доступ к ячейкам, вам нужна фабрика ячеек.

Следующий способ добавит такую ​​поддержку к столбцу. Он также уважает любую функциональность, определенную в ранее присоединенной клетки завода:

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 (cell.setOnDragEntered (cell.setOnDragEntered) e -> System.out.println («Введено»)); \t \t \t cell.setOnDragExited (e -> System.out.println («Exited»)); 'для получения информации, если событие запущено, но ничего не отображается, поэтому я не могу установить dropTarget. – Sunflame

Смежные вопросы