【发布时间】:2016-05-22 06:15:00
【问题描述】:
我有一个非常简单的拖放实现,它获取文件位置,然后在舞台上隐藏一些元素以显示有关文件的信息。但是,每当我尝试使用 setVisible() 或与舞台交互的任何其他命令时,我的程序就会完全陷入僵局。如果我在拖动文件后只有一个 println,它可以正常工作,但是当我有任何操作 UI 的逻辑时,它就会停止。
这是拖入文件后死锁的样子
"main@1" 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)
这是获取拖动事件的最小化 Main 方法。
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);
}
}
最小化控制器
package sample;
import javafx.scene.control.Button;
public class Controller {
public Button buttonTest;
}
最小化的 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>
我认为我可以通过将 dragEvent 拆分到它自己的线程中来处理这个问题,但是根据 javafx 中的并发规则,它无论如何都无法操纵舞台,因为所有图形都必须在主 javafxGUI 线程上。
希望有人能指出我正确的方向,谢谢!
【问题讨论】:
-
什么是
controller,你在哪里初始化它? -
@James_D 抱歉忘记包含了,我在start方法之前初始化了,它是fxml文件的控制器。
-
如果在start方法之前初始化fxml文件,它不可能是控制器。 fxml 文件的控制器是由
FXMLLoader在您调用load时创建的,因此在您的 start 方法的第一行完成之前它甚至还没有被实例化。 -
@James_D Welp,我之前有
Controller controller = new Controller();行,它似乎正在工作。 -
请edit 您的问题包含minimal reproducible example,而不是发布链接。至于访问控制器class,显然你可以这样做,但它没有帮助。您需要访问实际的控制器实例,而不是碰巧是同一类的其他任意对象。
标签: java multithreading javafx