2016-05-22 4 views
-2

mit Ich habe eine ziemlich einfache Implementierung eines Drag & Drop, die einen Speicherort der Datei bekommt und dann versteckt sich einige Elemente auf der Bühne Informationen über die Datei anzuzeigen. Allerdings wird mein Programm vollständig blockiert, wenn ich versuche, setVisible() oder einen anderen Befehl zu verwenden, der mit der Bühne interagiert. Wenn ich nur nach dem Ziehen mit der Datei einen Ausdruck habe, funktioniert es gut, aber sobald ich irgendeine Logik habe, die die Benutzeroberfläche manipuliert, stoppt sie einfach. DieseJavaFX Deadlock, wenn setVisible Methode mit Dragevent

ist, was aus der Sackgasse aussieht, nachdem eine Datei in

"[email protected]" prio=5 tid=0x1 nid=NA waiting 
    java.lang.Thread.State: WAITING 
     at sun.misc.Unsafe.park(Unsafe.java:-1) 
     at java.util.concurrent.locks.LockSupport.park(LockSupport.java:175) 
     at java.util.concurrent.locks.AbstractQueuedSynchronizer.parkAndCheckInterrupt(AbstractQueuedSynchronizer.java:836) 
     at java.util.concurrent.locks.AbstractQueuedSynchronizer.doAcquireSharedInterruptibly(AbstractQueuedSynchronizer.java:997) 
     at java.util.concurrent.locks.AbstractQueuedSynchronizer.acquireSharedInterruptibly(AbstractQueuedSynchronizer.java:1304) 
     at java.util.concurrent.CountDownLatch.await(CountDownLatch.java:231) 

gezogen wird hier das minimierte Hauptverfahren, das das Drag-Ereignis wird.

package sample; 

import javafx.application.Application; 
import javafx.event.EventHandler; 
import javafx.fxml.FXMLLoader; 
import javafx.scene.Parent; 
import javafx.scene.Scene; 
import javafx.scene.input.DragEvent; 
import javafx.scene.input.Dragboard; 
import javafx.scene.input.TransferMode; 
import javafx.stage.Stage; 

import java.io.File; 

public class Main extends Application { 

    @Override 
    public void start(Stage primaryStage) throws Exception{ 
     Parent root = FXMLLoader.load(getClass().getResource("sample.fxml")); 
     Scene scene = new Scene(root, 300, 275); 
     scene.setOnDragOver(new EventHandler<DragEvent>() { 
      @Override 
      public void handle(DragEvent event) { 
       Dragboard db = event.getDragboard(); 
       if (db.hasFiles()) { 
        event.acceptTransferModes(TransferMode.COPY); 
       } else { 
        event.consume(); 
       } 
      } 
     }); 
     scene.setOnDragDropped(new EventHandler<DragEvent>() { 
      @Override 
      public void handle(DragEvent event) { 

       Dragboard db = event.getDragboard(); 
       boolean success = false; 
       if (db.hasFiles()) { 
        success = true; 
        String filePath = null; 
        for (File file:db.getFiles()) { 
         filePath = file.getAbsolutePath(); 
         System.out.println(filePath); 
         Controller controller = new Controller(); 
         //Part where it crashes, 
         controller.buttonTest.setVisible(false); 
        } 
       } 
       event.setDropCompleted(success); 
       event.consume(); 
      } 
     }); 
     primaryStage.setTitle("Hello World"); 
     primaryStage.setScene(scene); 
     primaryStage.show(); 
    } 


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

Der minimierte-Controller

package sample; 
import javafx.scene.control.Button; 

public class Controller { 
    public Button buttonTest; 
} 

Die minimierte fxml

<?xml version="1.0" encoding="UTF-8"?> 
<?import javafx.scene.control.*?> 
<?import javafx.scene.layout.*?> 
<GridPane alignment="center" hgap="10" vgap="10" xmlns:fx="http://javafx.com/fxml/1" xmlns="http://javafx.com/javafx/8" fx:controller="sample.Controller"> 
    <columnConstraints> 
     <ColumnConstraints /> 
    </columnConstraints> 
    <rowConstraints> 
     <RowConstraints /> 
    </rowConstraints> 
    <children> 
     <Button fx:id="buttonTest" mnemonicParsing="false" text="Test" /> 
    </children> 
</GridPane> 

Ich dachte, ich könnte in der Lage sein, dies zu umgehen, indem das dragevent in seinen eigenen Thread Aufspalten aber nach den gemeinsamen Zugriff Regeln in javafx wäre es ohnehin nicht möglich, die Bühne zu manipulieren, da alle Grafiken im javafxGUI-Hauptthread liegen müssen.

der Hoffnung, jemand kann mir in die richtige Richtung weisen, danke!

+1

Was 'controller' ist und wo Initialisierst du es? –

+0

@James_D Entschuldigung vergessen zu schließen, ich initialisiere es vor der Start-Methode, es ist der Controller der fxml-Datei. – nmu

+1

Es kann unmöglich der Controller für die fxml-Datei sein, wenn Sie es vor der Startmethode initialisieren. Der Controller für die fxml-Datei wird vom 'FXMLLoader' beim Aufruf von' load' erstellt und wurde daher nicht instanziiert, bis die erste Zeile Ihrer Startmethode abgeschlossen ist. –

Antwort

1

Ihr Code erzeugt eine Null-Zeiger-Ausnahme, wenn Sie etwas auf das Fenster fallen, weil button nie in der Instanz von Controller, die Sie mit Controller controller = new Controller(); von Hand erstellen initialisiert wird.

Elemente, die in der fxml-Datei definiert sind, werden in der Controller-Instanz initialisiert, die dem FXMLLoader zugeordnet ist, wenn Sie load() aufrufen. Ich denke, was Sie hier versuchen, ist der Zugriff auf das Controller-Objekt. (Ich weiß nicht, warum Sie einen neuen erstellen.) Sie können dies tun, indem eine FXMLLoader Instanz erstellen und rief getController() darauf, statt der Verwendung der statische Belastungsmethode:

@Override 
public void start(Stage primaryStage) throws Exception{ 
    FXMLLoader loader = new FXMLLoader(getClass().getResource("sample.fxml")); 
    Parent root = loader.load(); 
    Controller controller = loader.getController(); 

    // ... 

    scene.setOnDragDropped(new EventHandler<DragEvent>() { 
     @Override 
     public void handle(DragEvent event) { 

      Dragboard db = event.getDragboard(); 
      boolean success = false; 
      if (db.hasFiles()) { 
       success = true; 
       String filePath = null; 
       for (File file:db.getFiles()) { 
        filePath = file.getAbsolutePath(); 
        System.out.println(filePath); 
        // Controller controller = new Controller(); 
        //Part where it crashes, 
        controller.buttonTest.setVisible(false); 
       } 
      } 
      event.setDropCompleted(success); 
      event.consume(); 
     } 
    }); 

    // ... 

} 
+0

Vielen Dank dafür, mit der fxml Loader-Instanz von Controller behoben, ich bin ziemlich neu in Javafx, so dass ich einfach angenommen, ein statisches Objekt würde den Trick tun. Ich bin auch gespannt was dir zeigt, dass es ein NullPointer war. Habe ich den falschen Thread in der Debug-Ausgabe angeschaut. Danke nochmal für die Hilfe! – nmu

+0

Keine Ahnung, was Sie gesucht haben: Ich habe es gerade ausgeführt (kein Debugger) und es gab eine Nullzeiger-Ausnahme in der Konsole (wie erwartet). Nicht sicher, was du mit "Ich nahm nur an, ein statisches Objekt würde den Trick tun": Sie haben keine statische Variable (es [würde nicht helfen, wenn Sie] (http://stackoverflow.com/questions/23105433)). –