En JavaFX (11), que estoy tratando de mostrar una ventana de alerta por encima de la ventana principal, pero no quiero que la ventana principal para hacer clic. Para ello, pensé que tenía que cambiar el initModality de esa ventana de alerta ( https://docs.oracle.com/javafx/2/api/javafx/stage/Stage.html ver 'Modalidad'). Por qué no funciona debido a que el propietario de la ventana de alerta es nulo?
Aquí está mi clase controlador. La clase principal es simplemente la clase JavaFX principal predeterminado generado por IntelliJ IDEA y el archivo .fxml es sólo un anchorpane con un botón para propósitos de prueba.
package sample;
import javafx.scene.control.Alert;
import javafx.scene.control.Button;
import javafx.stage.Modality;
public class Controller {
public Button button;
public void initialize(){
Alert alert = new Alert(Alert.AlertType.ERROR);
System.out.println(alert.getOwner()); //output: null
alert.initModality(Modality.APPLICATION_MODAL);
alert.setHeight(200);
alert.setWidth(300);
alert.show();
button.setOnAction(push -> System.out.println("button pressed")); //button is still pressable
}
}
El botón de la ventana principal sigue siendo prensada, por lo que el initModality no funcionaba. También he probado con Modality.WINDOW_MODAL
y Modality.NONE
, no hay cambio.
Estoy en Linux con bspwm si lo que importa.
Creo que el problema es el orden se muestran las ventanas. Prueba de esto con la siguiente reproducido el problema en Windows 10 (utilizando JavaFX 12.0.1):
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.Alert;
import javafx.scene.control.Alert.AlertType;
import javafx.scene.control.Label;
import javafx.scene.layout.StackPane;
import javafx.stage.Modality;
import javafx.stage.Stage;
public class Main extends Application {
@Override
public void start(Stage primaryStage) {
var alert = new Alert(AlertType.INFORMATION);
alert.initModality(Modality.APPLICATION_MODAL);
alert.setHeaderText(null);
alert.setContentText("This is a test of application modality.");
alert.show();
primaryStage.setScene(new Scene(new StackPane(new Label("Hello, World!")), 500, 300));
primaryStage.show();
}
}
Los resultados anteriores en una ventana de diálogo que no es propiamente modal. Sin embargo, si se muda alert.show()
a después de primaryStage.show()
todo funciona como se esperaba.
Puesto que usted está mostrando su Alert
interior el initialize()
método de un controlador de FXML, lo más probable es que el código se ejecuta antes de mostrar la ventana principal. Si desea visualizar la Alert
derecha en el comienzo de su aplicación existen al menos dos opciones:
Llamar
show()
dentro de unaPlatform.runLater
llamada, como lo hace en su respuesta .- La desventaja de esto es que hace que el código dependiente de código aparentemente sin relación altamente. Por ejemplo, si por cualquier razón usted cambia cómo y cuando se muestra la ventana principal, esta opción puede romper.
Agregue un método a su
Controller
clase y Invóquelo después de mostrar su otra ventana.@Override public void start(Stage primaryStage) throws IOException { FXMLLoader loader = new FXMLLoader(/*location*/); primaryStage.setScene(new Scene(loader.load())); primaryStage.show(); loader.<Controller>getController().showMyAwesomeAlert(); }