拖放在 Java 11 和 Java 8 中的工作方式不同 [英] Drag and Drop working differently in Java 11 vs Java 8

查看:42
本文介绍了拖放在 Java 11 和 Java 8 中的工作方式不同的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我写了一个在javafx中使用拖放的程序.在 JavaFX8 中它可以完美运行.

I wrote a program which makes use of drag and drop in javafx. In JavaFX8 it works perfectly.

在 JavaFX11 中,拖放功能不正常:我没有得到不同的鼠标光标,我没有得到我正在拖动的行的重影图像,而且拖放有问题——它们没有t 鼠标释放时触发,然后每次点击表格时都会触发 drop.

In JavaFX11, the drag and drop is dysfunctional: I don't get a different mouse cursor, I don't get a ghost image of the row I'm dragging, and something's wrong with the drops -- they don't trigger on mouse release, and then the drop is triggered each time I click on the table.

这是演示我面临的问题的最小可运行示例.在 Java 8 JVM 上运行,它可以按需要工作.在 Java 11 JVM 上它没有.我在 Ubuntu 18.04 上.

Here is minimum runnable example which demonstrates the issue I'm facing. Run on a Java 8 JVM it works as desired. On Java 11 JVM it does not. I am on Ubuntu 18.04.

我可以更改我的代码以适应 Java 11,但我不知道我做错了什么.

I'm fine with changing my code to accommodate Java 11, but I don't have any idea what I'm doing wrong.

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)

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 );
    }
}

Person.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"
    };
}

推荐答案

虽然 JavaFX 中的 Drag and Drop 有一个适用于所有平台的通用 API(当然是 API 的其余部分),但它的内部实现是依赖于平台的,它在 Windows、Mac 或 Linux 上完全不同.

While Drag and Drop in JavaFX has a common API for all the platforms (as the rest of the API, of course), its internal implementation is platform dependent, and it is quite different on Windows, Mac or Linux.

不过,从 JavaFX 8 迁移到 JavaFX 11 时,这应该不是问题.

But this shouldn't be an issue when migrating from JavaFX 8 to JavaFX 11, though.

OP 发布的示例在具有 JavaFX 8 和 11 的 Windows 和 Mac 上运行相同,如果在 Linux 上不是这种情况,则可能与最新版本的 JavaFX for Linux 中所做的更改有关.

The sample posted by the OP works the same on Windows and Mac with both JavaFX 8 and 11, and if it is not the case on Linux, it might have to do with the changes done in the latest release of JavaFX for Linux.

根据 发布说明,在Important Changes部分我们可以看到:

According to the releases note, under the Important Changes section we can see:

将默认 GTK 版本切换到 3

JavaFX 现在将在存在 gtk3 库的 Linux 平台上默认使用 GTK 3.在 JavaFX 11 之前,GTK 2 库是默认库.这与 JDK 11 中 AWT 的默认值匹配.有关详细信息,请参阅 JDK-8198654.

JavaFX will now use GTK 3 by default on Linux platforms where the gtk3 library is present. Prior to JavaFX 11, the GTK 2 library was the default. This matches the default for AWT in JDK 11. See JDK-8198654 for more information.

虽然这个 change 基本上是两行差异JavaFX 代码,DND 的实现细节没有任何变化,GTK 3 的实现可能从 GTK 2 发生了变化,这些变化没有被考虑在内.

While this change was basically a two lines diff in the JavaFX code, and nothing changed from the implementation details for DND, the GTK 3 implementation might have changed from GTK 2, and those changes haven't been taken into account.

对话框windowsWayland 崩溃.

解决方法

到目前为止,所有这些问题的唯一已知解决方法是使用 GTK 2 运行应用程序,可以使用系统属性进行设置:jdk.gtk.version.

So far the only known workaround for all of those issues is to run the app with GTK 2, that can be set with the system property: jdk.gtk.version.

所以这个选项可以在命令行中添加:

So this option can be added on command line:

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

运行应用程序.

正如评论中所说,这似乎解决了拖放问题.

As posted in the comments, this seems to solve the drag and drop issue.

报告问题

毫无疑问,这证实了这是一个问题,因此应该在 OpenJFX 问题上提交 tracker,提供重现它的示例代码、系统详细信息(OS 版本、Java 版本、JavaFX 版本...).

Definitely, that confirms that this is an issue, and as such it should be filed at the OpenJFX issue tracker, providing the sample code to reproduce it, system details (OS version, Java version, JavaFX version...).

这篇关于拖放在 Java 11 和 Java 8 中的工作方式不同的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆