javafx java-8 migration javafx-8 java-11

javafx - Arrastrar y soltar trabajando de forma diferente en Java 11 vs Java 8



java-8 migration (1)

Si bien Drag and Drop en JavaFX tiene una API común para todas las plataformas (como el resto de la API, por supuesto), su implementación interna depende de la plataforma y es bastante diferente en Windows, Mac o Linux.

Sin embargo, esto no debería ser un problema cuando se migra de JavaFX 8 a JavaFX 11.

El ejemplo publicado por el OP funciona igual en Windows y Mac con JavaFX 8 y 11, y si no es el caso en Linux, podría tener que ver con los cambios realizados en la última versión de JavaFX para Linux.

De acuerdo con la nota de lanzamiento , en la sección Important Changes podemos ver:

Cambia la versión GTK predeterminada a 3

JavaFX ahora usará GTK 3 por defecto en plataformas Linux donde la biblioteca gtk3 está presente. Antes de JavaFX 11, la biblioteca GTK 2 era la predeterminada. Esto coincide con el valor predeterminado para AWT en JDK 11. Consulte JDK-8198654 para obtener más información.

Si bien este change fue básicamente una diferencia de dos líneas en el código JavaFX, y nada cambió con respecto a los detalles de implementación para DND, la implementación de GTK 3 podría haber cambiado de GTK 2, y esos cambios no se han tenido en cuenta.

Se han informado problemas similares relacionados con GTK para dialogs , windows o choques de Wayland .

Solución

Hasta ahora, la única solución conocida para todos estos problemas es ejecutar la aplicación con GTK 2, que se puede configurar con la propiedad del sistema: jdk.gtk.version .

Así que esta opción se puede agregar en la línea de comando:

java -Djdk.gtk.version=2 ...

para ejecutar la aplicación.

Como se publicó en los comentarios, esto parece resolver el problema de arrastrar y soltar.

Reportar el problema

Definitivamente, eso confirma que esto es un problema y, como tal, debe archivarse en el tracker problemas de tracker , proporcionando el código de muestra para reproducirlo, los detalles del sistema (versión del SO, versión de Java, versión de JavaFX ...).

Escribí un programa que hace uso de arrastrar y soltar en javafx. En JavaFX8 funciona perfectamente.

En JavaFX11, el arrastrar y soltar es disfuncional: no obtengo un cursor de mouse diferente, no obtengo una imagen fantasma de la fila que estoy arrastrando, y algo está mal con las gotas, no se activan. la liberación del mouse, y luego la caída se activa cada vez que hago clic en la tabla.

Aquí hay un ejemplo de ejecución mínima que demuestra el problema al que me estoy enfrentando. Ejecutar en una JVM Java 8 funciona como se desee. En Java 11 JVM no lo hace. Estoy en Ubuntu 18.04.

Estoy bien con cambiar mi código para acomodar Java 11, pero no tengo idea de lo que estoy haciendo mal.

Versión de Java 11

java version "11.0.1" 2018-10-16 LTS Java(TM) SE Runtime Environment 18.9 (build 11.0.1+13-LTS) Java HotSpot(TM) 64-Bit Server VM 18.9 (build 11.0.1+13-LTS, mixed mode)

Versión de Java 8

openjdk version "1.8.0_181" OpenJDK Runtime Environment (build 1.8.0_181-8u181-b13-1ubuntu0.18.04.1-b13) OpenJDK 64-Bit Server VM (build 25.181-b13, mixed mode)

DND11.java

import javafx.application.Application; import javafx.collections.FXCollections; import javafx.scene.Scene; import javafx.scene.control.SelectionMode; import javafx.scene.control.TableColumn; import javafx.scene.control.TableRow; import javafx.scene.control.TableView; import javafx.scene.control.cell.PropertyValueFactory; import javafx.scene.input.ClipboardContent; import javafx.scene.input.DataFormat; import javafx.scene.input.Dragboard; import javafx.scene.input.TransferMode; import javafx.stage.Stage; public class DND11 extends Application { public TableView<Person> getTable () { DataFormat DRAGGED_PERSON = new DataFormat ( "application/example-person" ); TableColumn <Person, String> firstNameColumn = new TableColumn <> ( "First Name" ); TableColumn <Person, String> LastNameColumn = new TableColumn <> ( "Last Name" ); firstNameColumn.setCellValueFactory( new PropertyValueFactory <Person, String>( "firstName" ) ); LastNameColumn.setCellValueFactory( new PropertyValueFactory <Person, String>( "lastName" ) ); TableView <Person> tableView = new TableView <> (); tableView.getColumns().addAll( firstNameColumn, LastNameColumn ); tableView.setColumnResizePolicy( TableView.CONSTRAINED_RESIZE_POLICY ); tableView.setEditable( false ); tableView.setItems( FXCollections.observableArrayList( Person.generatePersons ( 10 ) ) ); tableView.getSelectionModel().setSelectionMode( SelectionMode.MULTIPLE ); tableView.setRowFactory( tv -> { TableRow <Person> row = new TableRow <>(); row.setOnDragDetected( event -> { if ( !row.isEmpty() ) { Dragboard db = row.startDragAndDrop( TransferMode.COPY ); ClipboardContent cc = new ClipboardContent(); cc.put( DRAGGED_PERSON, row.getItem() ); tableView.getItems().remove( row.getItem() ); db.setContent( cc ); } }); row.setOnDragOver( event -> { Dragboard db = event.getDragboard(); event.acceptTransferModes( TransferMode.COPY ); }); row.setOnDragDropped( event -> { Dragboard db = event.getDragboard(); Person person = (Person)event.getDragboard().getContent( DRAGGED_PERSON ); if ( person != null ) { tableView.getItems().remove( person ); int dropIndex = row.getIndex(); tableView.getItems().add( dropIndex, person ); } event.setDropCompleted( true ); event.consume(); }); return row; }); return tableView; } @Override public void start ( Stage stage ) throws Exception { stage.setScene( new Scene( getTable(), 800, 400 ) ); stage.show(); } public static void main ( String[] args ) { launch( args ); } }

Persona.java

import java.io.Serializable; import java.util.ArrayList; import java.util.List; import java.util.Random; public class Person implements Serializable { private static final long serialVersionUID = 1L; private String firstName, lastName; public Person ( String firstName, String lastName ) { this.firstName = firstName; this.lastName = lastName; } public String getFirstName() { return firstName; } public String getLastName() { return lastName; } public static List <Person> generatePersons ( int number ) { List<Person> retMe = new ArrayList<Person> ( number ); for ( int k = 0; k < number; k++ ) { retMe.add ( new Person ( randomFirstName(), randomLastName() ) ); } return retMe; } private static Random rand = new Random(); private static String randomFirstName() { return firstNames [ Math.abs( rand.nextInt() ) % firstNames.length ]; } private static String randomLastName() { return lastNames [ Math.abs( rand.nextInt() ) % lastNames.length ]; } private static String[] firstNames = new String[] { "ANTON","ANTONE","ANTONIA","NTONIO","ANTONY","ANTWAN","ARCHIE","ARDEN","ARIEL","ARLEN", "ARMAND","ARMANDO","ARNOLD","ARNOLDO","ARNULF","ARON","ARRON","ART","ARTHUR","ARTURO", "DARRICK","DARRIN","DARRON","DARRYL","DARWIN","DARYL","DAVE","DAVID","DAVIS","DEAN", }; private static String[] lastNames = new String[] { "SMITH","JOHNSON","WILLIAMS","BROWN","JONES","MILLER","DAVIS","GARCIA","RODRIGUEZ", "WILSON","MARTINEZ","ANDERSON","TAYLOR","THOMAS","HERNANDEZ","MOORE","MARTIN","JACKSON" }; }