需要从javaFX GUI线程调用JavaFX Popup吗?

时间:2015-05-11 14:22:22

标签: multithreading javafx javafx-8

我已将此控制器连接到带有多个按钮,标签,表格等的FXML文件。 我有一些弹出窗口被初始化并显示当点击不同的按钮并且工作正常。

我还有另一个弹出窗口,当出现问题时我想“弹出”,所以当从另一个类的java代码发送一个事件得到处理时调用它。

调用此消息弹出窗口,但Platform.runLater()中的代码未执行,实际上冻结了GUI。

我发现有一个区别似乎导致了这一点,那就是我在Platform.runLater()之前调用的Platform.isFxApplicationThread()在此消息弹出窗口中返回false,其中一个返回true通过按钮单击调用其他弹出窗口。

因为我还尝试过一个通常从按钮点击调用的弹出窗口,当从因为传入事件而被执行的代码中调用它时也不起作用,我很确定这是问题所在,但是Platform.runLater声明“可以从任何线程调用此方法,将Runnable发布到事件队列,然后立即返回给调用者。”对我来说这似乎不对,所以如果这实际上是问题,我有点不解......

之前有没有人遇到过这个和/或有没有人知道我做错了什么?

这很好用:

@FXML
private void btnCashClicked(ActionEvent event) {
    screensController.getCashTransactionController().addCashTransactionListener(this);
    labelToPay = new Label(eurosToPay + " euro");
    sealbagTextField = new SealbagTextField();
    PopupUtils.showCashPaymentPopup(btnSealbag, btnCashOk, labelPaid, labelSealbag, labelToPay, lblExchange,
            labelExchange, labelReturnValue, eurosToPay, btnCash, this, sealbagTextField);
    screensController.getMainController().startTransaction(amountInCents, PaymentType.Asap);
}

同一控制器类中的此代码不显示弹出窗口:

@Override
public void showErrorOnScreen(String message) {
    // temporary usage of label and textfield
    labelToPay = new Label(eurosToPay + " euro");
    sealbagTextField = new SealbagTextField();
    PopupUtils.showCashPaymentPopup(btnSealbag, btnCashOk, labelPaid, labelSealbag, labelToPay, lblExchange,
            labelExchange, labelReturnValue, eurosToPay, btnCash, this, sealbagTextField);
    //PopupUtils.showMessagePopup("Error", message, "Close", 374, 250, btnCancel);
}

我在Windows上使用jre1.8.0_60

cashPopup的代码:

public static int showCashPaymentPopup(Button btnSealbag, Button btnCashOk, Label labelPaid, Label labelSealbag, Label labelToPay, Label lblExchange, Label labelExchange, Label labelReturnAmount, int amount, Node node, PayScreen parent, SealbagTextField sealbagTextField) {
    int paid = 0;
    logger.debug("cashPopup is on GUI thread: " + Platform.isFxApplicationThread());
    Platform.runLater(new Runnable() {
        @Override
        public void run() {
            cashPopup.getContent().clear();
            Rectangle rectangle = new Rectangle();
            rectangle.setArcHeight(20);
            rectangle.setArcWidth(20);
            rectangle.setFill(Color.LIGHTBLUE);
            rectangle.setWidth(466);
            rectangle.setHeight(311);
            rectangle.setStroke(Color.DARKBLUE);
            rectangle.setStrokeType(StrokeType.INSIDE);

            ... 

            cashPopup.getContent().addAll(rectangle, textArea, headerLabel, lblDesc, lblAmount, labelAmount, lblPaid, labelPaid, lblToPay, labelToPay, btnCashOk, lblSealbag, labelSealbag, lblExchange, labelExchange, labelReturnAmount, btnSealbag, btnCancel);

            cashPopup.show(node, 150, 164);
        }
    });
    return paid;
}

showMessagePopup:

public static void showMessagePopup(String title, String text, String buttonText, int posX, int posY, Node parent) {
    logger.debug("messagePopup is on GUI thread: " + Platform.isFxApplicationThread());
    Platform.runLater(new Runnable() {
        @Override
        public void run() {
            logger.debug("0");
            messagePopup.getContent().clear();
            Rectangle rectangle = new Rectangle();
            rectangle.setArcHeight(20);
            rectangle.setArcWidth(20);
            rectangle.setFill(Color.LIGHTBLUE);
            rectangle.setWidth(500);
            rectangle.setHeight(300);
            rectangle.setStroke(Color.DARKBLUE);
            rectangle.setStrokeType(StrokeType.INSIDE);
            Label headerLabel = new Label(title);
            headerLabel.setStyle("-fx-font-size: 18; -fx-font-family: Arial;");
            headerLabel.setLayoutX(15);
            headerLabel.setLayoutY(10);
            TextArea textArea = new TextArea();
            textArea.setStyle("-fx-font-size: 14; -fx-font-family: Arial;");
            textArea.setLayoutX(10);
            textArea.setLayoutY(35);
            textArea.setMaxWidth(480);
            textArea.setMinHeight(190);
            textArea.setMaxHeight(190);
            textArea.setEditable(false);
            textArea.setWrapText(true);
            textArea.setText(text);

            Button btnClose =  new Button(buttonText);
            btnClose.setLayoutX(180);
            btnClose.setLayoutY(235);
            btnClose.setPrefSize(120, 54);
            btnClose.setStyle("-fx-font-size: 18; -fx-font-family: Arial; -fx-text-fill:white; -fx-background-color: linear-gradient(#8b9aa1, #456e84), linear-gradient(#c5dde7, #639fba), linear-gradient(#79abc1, #639fba); -fx-background-insets: 0,1,2; -fx-background-radius: 6,5,4;");
            btnClose.setOnAction(new EventHandler<ActionEvent>() {
                @Override
                public void handle(ActionEvent event) {
                    messagePopup.hide();
                }
            });
            messagePopup.getContent().addAll(rectangle, headerLabel, btnClose, textArea);
            messagePopup.show(parent, posX, posY);
        }
    });
}

logger.debug(“0”)甚至没有执行......

1 个答案:

答案 0 :(得分:-1)

通过在调试模式下运行并挂起Java FX线程来查看它正在做什么,找到它。 这个“其他线程”从主程序开始,需要在流程继续之前启动。这个其他线程看起来像这样:

    pinPadAsSlaveThread = new Thread(pinPadAsSlave);
    pinPadAsSlaveThread.start();
    while (!pinPadAsSlave.isRunning()) {
        // wait for pinPadAsSlave to be running
        try {
            Thread.sleep(10);
        } catch(InterruptedException ie) {
            // ignore
        }
    }

通常这需要大约50 ms,但由于引脚焊盘在网络上不可用,因此这将成为无限循环。当然,应该通过让这个循环只尝试50次左右来处理。 但真正的问题是这个连续10毫秒睡眠的线程是Java FX线程。我不知道为什么Java FX线程正在设置通信,因为它不应该(并且我没有通过将它放在platform.runLater或类似的东西中来要求),但事实是:它是......