【问题标题】:JavaFX 11 drag and drop works wrongly for gesture target after resizing him调整手势目标的大小后,JavaFX 11 拖放对手势目标无效
【发布时间】:2021-05-24 12:53:20
【问题描述】:

我遇到了下一个问题.. 我在我的应用程序中添加了一个简单的 drag-n-drop 功能,以将卡片从左右 ListView 移动到中心表。该表只是一个GridView。网格子元素完美接收到任何拖动事件,没关系。

但是.. 如果我调整应用程序窗口的大小,我无法将卡片拖动到 GridView 的右侧和底部。可能这个 GridView 只是调整大小,但 JavaFX 拖动提供程序只是使用旧边界?我如何修复它并向拖动提供者“说”新的 GridView 尺寸?

工作环境:

  • Oracle JDK 11.0.9
  • 自定义 JavaFX 11.0.2 运行时映像
  • Linux(内核 5.10.11,内部版本 170)
  • GTK 2(使用 -Djdk.gtk.version=2 为 JFX 应用程序指定)

DragAndDropProvider.java(主 DnD 类):

public class DragAndDropProvider {
    
    public static final DataFormat SUBJECT_DATA_FORMAT = new DataFormat(SubjectCard.class.getName());
    public static final DataFormat TEACHER_DATA_FORMAT = new DataFormat(TeacherCard.class.getName());

    public static <T extends DatabaseCellDto<CARD>, CARD> void allowDragSourceFeature(ListView<T> listView) {
        listView.getSelectionModel().setSelectionMode(SelectionMode.SINGLE);
        listView.setOnDragDetected(event -> dragDetected(event, listView));
        listView.setOnDragDone(event -> dragDone(event, listView));
    }
    
    public static void allowDragTargetFeature(LessonDto lesson) {
        lesson.setOnDragOver(DragAndDropProvider::dragOver);
    }
    
    private static <T extends DatabaseCellDto<CARD>, CARD> void dragDetected(MouseEvent event, ListView<T> listView) {
        // make sure at list item is selected
        T selectedItem = listView.getSelectionModel().getSelectedItem();
        if(selectedItem == null) {
            event.consume();
            return;
        }
        
        // determining the date format
        DataFormat dataFormat;
        CARD card = selectedItem.getCard();
        
        if(card instanceof SubjectCard)
            dataFormat = SUBJECT_DATA_FORMAT;
        else if(card instanceof TeacherCard)
            dataFormat = TEACHER_DATA_FORMAT;
        else
            throw new RuntimeException("Unsupported transfer object type: " + card.getClass().getSimpleName());
 
        // initiate a drag-and-drop gesture
        Dragboard dragboard = listView.startDragAndDrop(TransferMode.ANY);
 
        // put the selected item to the dragboard
        ClipboardContent content = new ClipboardContent();
        content.put(dataFormat, selectedItem.getCard());
 
        dragboard.setContent(content);
        event.consume();
    }
 
    private static void dragOver(DragEvent event) {
        // if drag board has an ITEM_LIST and it is not being dragged
        // over itself, we accept the MOVE transfer mode
        Dragboard dragboard = event.getDragboard();
 
        if(dragboard.hasContent(SUBJECT_DATA_FORMAT) || dragboard.hasContent(TEACHER_DATA_FORMAT))
            event.acceptTransferModes(TransferMode.ANY);
 
        event.consume();
    }
 
    private static void dragDropped(DragEvent event, LessonDto target) {
        // transfer the data to the target
        Dragboard dragboard = event.getDragboard();
        boolean dragCompleted = false;
 
        if(dragboard.hasContent(SUBJECT_DATA_FORMAT)) {
            SubjectCard content = (SubjectCard) dragboard.getContent(SUBJECT_DATA_FORMAT);
            target.updateSubject(content);
            dragCompleted = true;
        } else if(dragboard.hasContent(TEACHER_DATA_FORMAT)) {
            TeacherCard content = (TeacherCard) dragboard.getContent(TEACHER_DATA_FORMAT);
            target.updateTeacher(content);
            dragCompleted = true;
        }
 
        event.setDropCompleted(dragCompleted);
        event.consume();
    }

}

应用程序界面(俄语,抱歉):

【问题讨论】:

标签: java javafx java-11


【解决方案1】:

我的问题解决了。 解决方案非常简单。 当应用程序窗口最大化时,舞台的大小仍然是默认的,这是在初始化时设置的。 (例如,700 x 500)但实际上必须是 1366 x 768(这是我的屏幕分辨率)。

我只是使用此代码来修复它。 只需在初始化 FXML 控制器后插入此代码 :)

        // stage is the window stage
        // we need the maximized property that mean is window maximized or not
        stage.maximizedProperty().addListener((a, b, isMaximized) -> {
            if(isMaximized) {
                // if this window is maximized, then we use
                // bounds maxX and maxY values than equals your
                // screen size parameters
                
                // mainPane is a root element in your FXML file
                // just set any FX:ID for that and use it here
                
                // you also can try Scene#getParent (cast to Region or any children)
                // to use him size parameters, but I prefer to use that
                stage.setWidth(mainPane.getBoundsInParent().getMaxX());
                stage.setHeight(mainPane.getBoundsInParent().getMaxY());
            } else {
                // overwise after window minimazing we just restore default
                // size parameters saved in the stage object
                stage.setWidth(stage.getWidth());
                stage.setHeight(stage.getHeight());
            }
        });

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多