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

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

问题描述

我编写了一个在javafx中使用拖放功能的程序。在JavaFX8中它完美运行。



在JavaFX11中,拖放功能失效:我没有得到不同的鼠标光标,我没有得到我拖动的行的鬼像滴水有问题 - 它们不会在鼠标释放时触发,然后每次点击表格时都会触发掉落。



这是最低限度可运行的例子,它展示了我面临的问题。在Java 8 JVM上运行它可以根据需要运行。在Java 11 JVM上它没有。我在Ubuntu 18.04上。



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



Java 11版本

  java版本11.0.12018 -10-16 LTS 
Java(TM)SE运行时环境18.9(版本11.0.1 + 13-LTS)
Java HotSpot(TM)64位服务器VM 18.9(版本11.0.1 + 13- LTS,混合模式)

Java 8版本

  openjdk version1.8.0_181
OpenJDK Runtime Environment(build 1.8.0_181-8u181-b13-1ubuntu0.18.04.1-b13)
OpenJDK 64位服务器VM(版本25.181-b13,混合模式)

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;

公共类DND11扩展应用程序{

public TableView< Person> getTable(){
DataFormat DRAGGED_PERSON = new DataFormat(application / example-person);

TableColumn< Person,String> firstNameColumn = new TableColumn<> ( 名字 );
TableColumn< Person,String> LastNameColumn = new TableColumn<> ( 姓 );

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 .getDragbo ard()。getContent(DRAGGED_PERSON);

if(person!= null){
tableView.getItems()。remove(person);
int dropIndex = row.getIndex();
tableView.getItems()。add(dropIndex,person);
}

event.setDropCompleted(true);
event.consume();
});

返回行;
});

返回tableView;
}

@Override
public void start(阶段阶段)抛出异常{
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实现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;
}

公共静态列表< Person> generatePersons(int number){
List< Person> retMe = new ArrayList< Person> (数字);
for(int k = 0; k< number; k ++){
retMe.add(new Person(randomFirstName(),randomLastName()));
}
返回retMe;
}


private static随机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中拖放有一个适用于所有平台的通用API(当然,作为API的其余部分),其内部实现依赖于平台,在Windows,Mac或Linux上有很大的不同。



但是,从JavaFX 8迁移到JavaFX 11时,这不应该是一个问题。



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



根据发布说明,在重要更改部分下我们可以看到:


将默认GTK版本切换为3



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


更改基本上是JavaFX代码中的两行差异,并且没有从实现细节中改变DND,GTK 3实施可能已从GTK 2更改,并且未考虑这些更改。



有关GTK的类似问题已报告为对话框 windows Wayland崩溃



解决方法



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



因此可以在命令行中添加此选项:

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

运行该应用程序。



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



报告问题



当然,这确认这是一个问题,因此应该在OpenJFX问题上提交 tracker ,提供重现它的示例代码,系统详细信息(操作系统版本,Java版本,JavaFX版本......)。 / p>

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

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.

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.

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 Version

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 Version

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

解决方案

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.

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

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.

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

Switch default GTK version to 3

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.

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.

Similar issues related to GTK have been reported for dialogs, windows or Wayland crashes.

Workaround

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 ...

to run the application.

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

Report the issue

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天全站免登陆