Android-тост в JavaFX

Я новичок в JavaFX, и мне интересно, есть ли какой-то эквивалент Android Toast? Я видел класс Notification, но не похоже, что он может отображаться только в приложении. Я также нашел, что могу пользователь Timer и сделать затенение Label, но если есть какой-то класс для использования, я бы лучше!

Спасибо!

Ответ 1

Попробуйте третью сторону Панель уведомлений или уведомлений ControlsFX.

"Элемент управления NotificationPane позволяет вам уведомлять своих пользователей о чем-то, не требуя их немедленного ввода (что вы можете сделать с помощью API-интерфейсов ControlsFX). NotificationPane будет анимировать и выходить из вида"

toast1

Уведомления "покажет сообщение уведомления пользователям в одном из девяти мест на экране... После установленной продолжительности уведомление будет исчезать."

toast2

Ответ 2

Я знаю, что прошло много времени с тех пор, как вы опубликовали это сообщение, но я только что сделал андроидальное сообщение для тоста для javafx, поэтому отправлю его здесь, если кому-то нужен такой код.

import javafx.animation.KeyFrame;
import javafx.animation.KeyValue;
import javafx.animation.Timeline;
import javafx.scene.Scene;
import javafx.scene.layout.StackPane;
import javafx.scene.paint.Color;
import javafx.scene.text.Font;
import javafx.scene.text.Text;
import javafx.stage.Stage;
import javafx.stage.StageStyle;
import javafx.util.Duration;

public final class Toast
{
    public static void makeText(Stage ownerStage, String toastMsg, int toastDelay, int fadeInDelay, int fadeOutDelay)
    {
        Stage toastStage=new Stage();
        toastStage.initOwner(ownerStage);
        toastStage.setResizable(false);
        toastStage.initStyle(StageStyle.TRANSPARENT);

        Text text = new Text(toastMsg);
        text.setFont(Font.font("Verdana", 40));
        text.setFill(Color.RED);

        StackPane root = new StackPane(text);
        root.setStyle("-fx-background-radius: 20; -fx-background-color: rgba(0, 0, 0, 0.2); -fx-padding: 50px;");
        root.setOpacity(0);

        Scene scene = new Scene(root);
        scene.setFill(Color.TRANSPARENT);
        toastStage.setScene(scene);
        toastStage.show();

        Timeline fadeInTimeline = new Timeline();
        KeyFrame fadeInKey1 = new KeyFrame(Duration.millis(fadeInDelay), new KeyValue (toastStage.getScene().getRoot().opacityProperty(), 1)); 
        fadeInTimeline.getKeyFrames().add(fadeInKey1);   
        fadeInTimeline.setOnFinished((ae) -> 
        {
            new Thread(() -> {
                try
                {
                    Thread.sleep(toastDelay);
                }
                catch (InterruptedException e)
                {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
                   Timeline fadeOutTimeline = new Timeline();
                    KeyFrame fadeOutKey1 = new KeyFrame(Duration.millis(fadeOutDelay), new KeyValue (toastStage.getScene().getRoot().opacityProperty(), 0)); 
                    fadeOutTimeline.getKeyFrames().add(fadeOutKey1);   
                    fadeOutTimeline.setOnFinished((aeb) -> toastStage.close()); 
                    fadeOutTimeline.play();
            }).start();
        }); 
        fadeInTimeline.play();
    }
}

Вы можете сделать сообщение с тостом из любого класса с помощью этого кода:

String toastMsg = "some text...";
int toastMsgTime = 3500; //3.5 seconds
int fadeInTime = 500; //0.5 seconds
int fadeOutTime= 500; //0.5 seconds
Toast.makeText(primarystage, toastMsg, toastMsgTime, fadeInTime, fadeOutTime);

Ответ 3

Чтобы создать собственный тост, используя собственный макет fxml:

package controllers;

import javafx.animation.KeyFrame;
import javafx.animation.Timeline;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.scene.Scene;
import javafx.scene.control.Control;
import javafx.scene.control.Label;

import javafx.scene.layout.HBox;
import javafx.stage.Modality;
import javafx.stage.Stage;
import javafx.stage.StageStyle;
import javafx.util.Duration;

import java.io.IOException;


public class ToastController {

    public static final int TOAST_SUCCESS = 11;
    public static final int TOAST_WARN = 12;
    public static final int TOAST_ERROR = 13;

    @FXML
    private HBox containerToast;

    @FXML
    private Label textToast;

    private void setToast(int toastType, String content){
        textToast.setText(content);
        switch (toastType){
            case TOAST_SUCCESS:
                containerToast.setStyle("-fx-background-color: #9FFF96");
                break;
            case TOAST_WARN:
                containerToast.setStyle("-fx-background-color: #FFCF82");
                break;
            case TOAST_ERROR:
                containerToast.setStyle("-fx-background-color: #FF777C");
                break;
        }
    }

    public static void showToast(int toastTyoe, Control control, String text){
        Stage dialog = new Stage();
        dialog.initOwner(control.getScene().getWindow());
        dialog.initModality(Modality.APPLICATION_MODAL);
        dialog.setResizable(false);
        dialog.initStyle(StageStyle.UNDECORATED);

        double dialogX = dialog.getOwner().getX();
        double dialogY = dialog.getOwner().getY();
        double dialogW = dialog.getOwner().getWidth();
        double dialogH = dialog.getOwner().getHeight();

        double posX = dialogX + dialogW/2;
        double posY = dialogY + dialogH/6 *5;
        dialog.setX(posX);
        dialog.setY(posY);

        try {
            FXMLLoader loader = new FXMLLoader();
            loader.setLocation(ToastController.class.getResource("/fxml/toastPopup.fxml"));
            loader.load();
            ToastController ce = loader.getController();
            ce.setToast(toastTyoe,text);
            dialog.setScene(new Scene(loader.getRoot()));
            dialog.show();
            new Timeline(new KeyFrame(
                    Duration.millis(1500),
                    ae -> {
                        dialog.close();
                    })).play();
        } catch (IOException ex) {
            ex.printStackTrace();
        }
    }
}

FXML:

<?xml version="1.0" encoding="UTF-8"?>

<?import javafx.geometry.Insets?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.layout.HBox?>
<?import javafx.scene.text.Font?>


<HBox fx:id="containerToast" alignment="CENTER" xmlns="http://javafx.com/javafx/8.0.171" xmlns:fx="http://javafx.com/fxml/1" fx:controller="controllers.ToastController">
   <children>
      <Label fx:id="textToast" text="TEST" textAlignment="CENTER">
         <font>
            <Font name="System Bold" size="16.0" />
         </font>
      </Label>
   </children>
   <padding>
      <Insets bottom="5.0" left="5.0" right="5.0" top="5.0" />
   </padding>
</HBox>

чтобы запустить тост, просто используйте:
Один из 3 видов тостов:
ToastController.TOAST_ERROR
ToastController.TOAST_SUCCESS
ToastController.TOAST_WARN


@FXML
private Label idOfAnyControl;

showToast(ToastController.TOAST_WARN,idOfAnyControl,"ERROR TEXT")


если вы хотите, вы можете извлечь 2 дополнительных параметра путем внедрения зависимости (время и положение тоста)

Ответ 4

Отличная работа @alcoolis! Спасибо! Работайте нормально для меня, если я изменю параметр primaryStage на null. Я не знаю причину:

//это работает

Toast.makeText(null, toastMsg, toastMsgTime, fadeInTime, fadeOutTime);

Ответ 5

@alcoolis эквивалент в котлине

Toast.makeText(primaryStage, "No data selected!")


class Toast {

companion object {
    fun makeText(stage: Stage, message: String, displayTime: Int = 3000, fadeInDelay: Int = 500, fadeOutDelay: Int = 500, size: Double = 15.0, opacity: Double = 5.0) {
        val toastStage = Stage()
        toastStage.initOwner(stage)
        toastStage.isResizable = false
        toastStage.initStyle(StageStyle.TRANSPARENT)

        val text = Text(message)
        text.font = Font.font("Verdana", size)
        text.fill = Color.RED

        val root = StackPane(text)
        root.style = "-fx-background-radius: 20; -fx-background-color: rgba(0, 0, 0, 0.2); -fx-padding: 50px;"
        root.opacity = opacity

        val scene = Scene(root)
        scene.fill = Color.TRANSPARENT
        toastStage.scene = scene
        toastStage.show()

        val fadeInTimeline = Timeline()
        val fadeInKey1 =
            KeyFrame(Duration.millis(fadeInDelay.toDouble()), KeyValue(toastStage.scene.root.opacityProperty(), 1))
        fadeInTimeline.keyFrames.add(fadeInKey1)
        fadeInTimeline.setOnFinished {
            Thread {
                try {
                    Thread.sleep(displayTime.toLong())
                } catch (e: InterruptedException) {
                    // TODO Auto-generated catch block
                    e.printStackTrace()
                }

                val fadeOutTimeline = Timeline()
                val fadeOutKey1 =
                    KeyFrame(
                        Duration.millis(fadeOutDelay.toDouble()),
                        KeyValue(toastStage.scene.root.opacityProperty(), 0)
                    )
                fadeOutTimeline.keyFrames.add(fadeOutKey1)
                fadeOutTimeline.setOnFinished { toastStage.close() }
                fadeOutTimeline.play()
            }.start()
        }
        fadeInTimeline.play()
    }
}

}