2017-10-18 63 views
1

我在拖放操作期間使用彈出對話框。當下降發生時會彈出一個對話框,當它被解散時,事件鏈應該繼續,並且在拖動操作結束時允許發生某些事情。如果彈出對話框是FX,那麼沒有問題,但如果它是Gluon,則拖動完成操作不會發生。對話框導致拖動完成事件不傳播

下面是一個示例的代碼:在其上的背景變爲紅色

import javafx.scene.control.Alert.AlertType; 
import javafx.scene.control.Label; 
import javafx.scene.input.ClipboardContent; 
import javafx.scene.input.DataFormat; 
import javafx.scene.input.Dragboard; 
import javafx.scene.input.TransferMode; 
import javafx.scene.layout.Background; 
import javafx.scene.layout.BackgroundFill; 
import javafx.scene.layout.HBox; 
import javafx.scene.paint.Color; 

import com.gluonhq.charm.glisten.mvc.View; 

public class MainView extends View { 

    HBox root; 

    public MainView(String name) { 
     super(name); 

     Label source = new Label("Source"); 
     configureDragSource(source); 
     Label target = new Label("Target"); 
     configureDragTarget(target); 
     Label popupTarget = new Label("Popup Target"); 
     configureDragPopupTarget(popupTarget); 
     root = new HBox(40, source, target, popupTarget); 
     setCenter(root); 
    } 

    private void configureDragSource(Label source) { 
     source.setOnDragDetected(e -> { 
      root.setBackground(new Background(new BackgroundFill(Color.RED, null, null))); 
      Dragboard db = source.startDragAndDrop(TransferMode.ANY); 
      ClipboardContent content = new ClipboardContent(); 
      content.put(DataFormat.PLAIN_TEXT, source.getText()); 
      db.setContent(content); 
     }); 
     source.setOnDragDone(e -> root.setBackground(new Background(new BackgroundFill(null, null, null)))); 
    } 

    private void configureDragTarget(Label target) { 
     target.setOnDragOver(e -> e.acceptTransferModes(TransferMode.ANY)); 

    } 

    private void configureDragPopupTarget(Label popupTarget) { 
     popupTarget.setOnDragOver(e -> e.acceptTransferModes(TransferMode.ANY)); 
     popupTarget.setOnDragDropped(e -> { 
      javafx.scene.control.Alert popup1 = new javafx.scene.control.Alert(AlertType.INFORMATION); 
      com.gluonhq.charm.glisten.control.Alert popup2 = new com.gluonhq.charm.glisten.control.Alert(AlertType.INFORMATION); 
      popup1.showAndWait(); 
     }); 
    } 
} 

源應被拖動。拖動操作完成後,背景應該恢復爲默認值。常規放置目標什麼都不做,顏色變化起作用。但是,當彈出目標時彈出對話框,當它關閉時,顏色只會改變FX對話框而不改變膠子對話框。將popup1.showAndWait();更改爲popup2

如果重要的是這樣的應用程序類

import com.gluonhq.charm.glisten.application.MobileApplication; 

public class TestApplication extends MobileApplication { 

    @Override 
    public void init() { 
     addViewFactory(HOME_VIEW,() -> new MainView(HOME_VIEW)); 
    } 

    public static void main(String[] args) { 
     launch(args); 
    } 
} 

,這是gradle這個構建文件:

buildscript { 
    repositories { 
     jcenter() 
    } 
    dependencies { 
     classpath 'org.javafxports:jfxmobile-plugin:1.3.5' 
    } 
} 

apply plugin: 'org.javafxports.jfxmobile' 
apply plugin: 'eclipse' 

jar { 
    manifest { 
     attributes 'Main-Class': 'com.test.TestApplication' 
    } 
} 

jfxmobile { 
    downConfig { 
     version = '3.3.0' 
     plugins 'display', 'lifecycle', 'statusbar', 'storage' 
    } 
    android { 
     compileSdkVersion = 19 
//  manifest = 'src/android/AndroidManifest.xml' 
    } 
    ios { 
     infoPList = file('src/ios/Default-Info.plist') 
     forceLinkClasses = [ 
       'com.gluonhq.**.*', 
       'javax.annotations.**.*', 
       'javax.inject.**.*', 
       'javax.json.**.*', 
       'org.glassfish.json.**.*' 
     ] 
    } 
} 

eclipse { 
    classpath { 
     downloadJavadoc = true 
     downloadSources = true 
    } 
} 

repositories { 
    jcenter() 
    maven { 
     url 'http://nexus.gluonhq.com/nexus/content/repositories/releases' 
    } 
} 

mainClassName = 'com.test.TestApplication' 

dependencies { 
    compile 'com.gluonhq:charm:4.3.5' 
} 

task wrapper(type: Wrapper) { 
    gradleVersion = '4.2' 
} 

也發生在compile 'com.gluonhq:charm:4.3.7'和4.4.0。

在Java 8 b141上運行。爲什麼會發生?這是一個錯誤?

+0

在Dialog javadoc頁面上,BTW命令行'dialog.setContent(new Label(「只是一個普通對話框,簡單而簡單」);'缺少'''''。 – Mark

+0

當您在桌面上使用'popup2'運行時,您是否看到NPE? –

+0

@JoséPereda號我還在事件處理程序中加入了try catch,並且沒有發現任何東西。我應該看一個特定的地方嗎? – Mark

回答

1

JavaFX內置對話框和Gluon對話框不一樣。事實上,後者從Layer延伸,而模態和阻塞,如前者。

在Mac上運行張貼代碼,我得到一個NPE下降超過popupTarget後,可以使用容易解決:

Platform.runLater(() -> popup2.showAndWait()); 

此外,鑑於拖動事件是由對話框,一個可能的解決方案消耗可能是:

Platform.runLater(() -> 
    popup2.showAndWait() 
     .ifPresent(r -> 
      root.setBackground(new Background(new BackgroundFill(null, null, null))))); 

所以,你可以重構setOnDragDone法,只需創建一個對話框被關閉以及之後可能被調用的方法。

編輯

這些是兩個目標和源收到一旦DND事件已開始拖動事件:

目標接收拖累這些事件拖放手勢:

DRAG_OVER 
DRAG_OVER 
... // until drop is done: 
// show Dialog 
... 
// hide Dialog 
DRAG_DROPPED 
DRAG_EXITED 
DRAG_EXITED_TARGET 

這些工作與JavaFX和Gluon對話框完全相同(至少在Windows上)。在Mac上,由於NPE,使用Platform.runLater()顯然延遲顯示對話框並隱藏對話事件,但現在讓我們只關注Windows)。

正確的,最後一場比賽後,源接收:

DRAG_DONE 

但只有一個JavaFX對話框。

一些調試後,之所以膠子的對話中止拖拽完成事件可以解釋如下:

Scene類有一個DnDGesture私有類:

/** 
* A Drag and Drop gesture has a lifespan that lasts from mouse 
* PRESSED event to mouse RELEASED event. 
*/ 
class DnDGesture { 
    ... 
} 

而且因爲它是解釋在評論中,它具有從鼠標按下事件到鼠標釋放事件的使用壽命。

使用JavaFX內置對話框,這會顯示在新的舞臺上,因此會顯示新的場景。這裏的關鍵是,這個對話框(以及所有的鼠標事件集合)都會在一個新的模式階段中顯示出來,所以一旦對話框被隱藏起來,主階段就會重新獲得焦點並恢復,並且正確地完成dnd手勢,因爲鼠標是釋放。

但使用膠子的對話框,沒有第二階段。一切發生在同一階段,一旦鼠標被釋放,Scene.DnDGesture變爲空,所以當DRAG_EXITED_TARGET事件發生在目標中時,正確的調用完成了dnd過程,但此時dndGesture爲空,通話不再來源。

我不認爲這是一個錯誤,但更像是一種折衷,因爲有很多原因可以避免移動環境中的第二階段/場景,並保持View/Layer(在單一階段中)設計。

+0

是的,目前我的解決方法是調用拖放完成的事件處理程序,拖放內容類似於你在第二個示例中只做了runLater,因爲我沒有收到任何錯誤。膠子對話框的行爲不是像本地人那樣行事?這會被認爲是一個錯誤? – Mark

+0

我已經編輯了我的答案,並進一步解釋了發生了什麼,以及爲什麼我不認爲它是一個錯誤。 –

相關問題