Como eu faço pra chamar uma Application várias vezes no JavaFX?

Olá, eu sou iniciante no JavaFX, e no meu projeto eu gostaria de fazer algo como o setVisible da JFrame em uma Application do JavaFX. Alguém sabe me explicar como eu faço isso? Eu li que elas só podem ser chamadas uma vez. Tentei várias gambiarras como deixar o stage estático, dentre outras coisas, mas nada funcionou.

Eu encontrei uma solução, mas desde já peço, se alguém achar que ficou meio gambiarra, me de uma solução melhor por favor. Eu não gostei assim, mas está funcionando pelo menos.

A classe da minha janela:

public class GoogleSignIn {

	private static Stage stage = new Stage();
	
	public static void start() throws IOException{
		Pane root = FXMLLoader.load(GoogleSignIn.class.getResource("/fxml/GoogleSignIn.fxml"));
		Scene scene = new Scene(root,818,641);
		stage.setScene(scene);
		stage.setTitle("Conectar-se");
		stage.show();
	}
	
}

E daí das outras classes eu só chamo;

GoogleSignIn.start();

Olá, criei uma classe utilitária que faz isso há um tempo, basicamente é um controller customizado, com eventos de show() -> equivalente ao setVisible(true), showModal entre outros.

Exemplo:

O código está aqui:


1 curtida

Gostei da sua ideia, é realmente bem útil. Mas sobre a classe TopMsg, onde eu encontro ela?

Essa foi é uma classe utilitária pra mostrar alertas, substitua por Alert.

O que eu passo como parâmetro do show? Minha janela não tem pai.

Passe null.

Passando null é retornado isso

LOAD VIEW
java.lang.RuntimeException: O painel principal não foi definido, sobreescreva o método getFXML ou getRootPane!
	at com.tkfentretenimento.meusdados.controller.WindowController.loadView(WindowController.java:153)
	at com.tkfentretenimento.meusdados.controller.WindowController.createShow(WindowController.java:164)
	at com.tkfentretenimento.meusdados.controller.WindowController.show(WindowController.java:158)
	at com.tkfentretenimento.meusdados.view.GoogleSignIn.displayWindow(GoogleSignIn.java:33)
	at com.tkfentreteniment.meusdados.start.Start.main(Start.java:15)

Faça conforme o exemplo, a exception é bem clara, e esse erro não ocorre por falta do pai. Basicamente no seu controller vc tem que apontar qual é o fxml que ele vai carregar.

Eu tinha uma application que carregava o fxml, então agora eu posso deleta-la e carregar direto no controller com o getFxml?

Sim, é isso mesmo. Mas passe todo o caminho do fxml.

Eu passei o caminho completo e verifiquei com um print, aparentemente não tem nada errado, e foi retornado esta exceção:

C:/Users/thall/workspace/Meus-Dados/target/classes/fxml/GoogleSignIn.fxml
Location is not set. - false
java.lang.IllegalStateException: Location is not set.
	at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:2434)
	at javafx.fxml.FXMLLoader.load(FXMLLoader.java:2409)
	at com.tkfentretenimento.meusdados.controller.WindowController.loadView(WindowController.java:130)
	at com.tkfentretenimento.meusdados.controller.WindowController.createShow(WindowController.java:164)
	at com.tkfentretenimento.meusdados.controller.WindowController.show(WindowController.java:158)
	at com.tkfentreteniment.meusdados.start.Start.main(Start.java:15)

O caminho começa a partir do /fxml ao que me parece. O que estiver antes disso é desnecessário. Quando falo “caminho” é relativo ao classpath da aplicação.

Eu fiz assim:

@Override
public String getFXML() {
    return getClass().getResource("/fxml/GoogleSignIn.fxml").toString().replace("file:/", "");
}

Não precisa, só passe a string “/fxml/GoogleSignIn.fxml”. O resto a classe faz

Okay, eu coloquei, e não tem mais problemas em localizar o arquivo, porém está sendo lançada agora uma exceção que eu nunca vi antes:

Exception in thread "main" java.lang.ExceptionInInitializerError
	at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
	at sun.reflect.NativeConstructorAccessorImpl.newInstance(Unknown Source)
	at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(Unknown Source)
	at java.lang.reflect.Constructor.newInstance(Unknown Source)
	at java.lang.Class.newInstance(Unknown Source)
	at sun.reflect.misc.ReflectUtil.newInstance(Unknown Source)
	at javafx.fxml.FXMLLoader$InstanceDeclarationElement.constructValue(FXMLLoader.java:1009)
	at javafx.fxml.FXMLLoader$ValueElement.processStartElement(FXMLLoader.java:746)
	at javafx.fxml.FXMLLoader.processStartElement(FXMLLoader.java:2707)
	at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:2527)
	at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:2441)
	at javafx.fxml.FXMLLoader.load(FXMLLoader.java:2409)
	at com.tkfentretenimento.meusdados.controller.WindowController.loadView(WindowController.java:130)
	at com.tkfentretenimento.meusdados.controller.WindowController.createShow(WindowController.java:164)
	at com.tkfentretenimento.meusdados.controller.WindowController.show(WindowController.java:158)
	at com.tkfentreteniment.meusdados.start.Start.main(Start.java:15)
Caused by: java.lang.IllegalStateException: Toolkit not initialized
	at com.sun.javafx.application.PlatformImpl.runLater(PlatformImpl.java:273)
	at com.sun.javafx.application.PlatformImpl.runLater(PlatformImpl.java:268)
	at com.sun.javafx.application.PlatformImpl.setPlatformUserAgentStylesheet(PlatformImpl.java:550)
	at com.sun.javafx.application.PlatformImpl.setDefaultPlatformUserAgentStylesheet(PlatformImpl.java:512)
	at javafx.scene.control.Control.<clinit>(Control.java:87)
	... 16 more

Vou colocar essas classes em uma biblioteca e disponibilizar no git, quando concluir posto o link aqui.

Fico aguardando. Sua biblioteca é realmente útil, poupa várias linhas de código. Mas sobre a exceção, tem ideia do que causou?

Não, nunca vi esse erro. Talvez algum erro de implementação. Só da pra saber vendo o código.

Claro, aqui está:

import javafx.scene.web.WebView;

import java.net.URL;
import java.sql.SQLException;
import java.text.ParseException;
import java.util.ResourceBundle;

import com.tkfentretenimento.meusdados.model.Constants;
import com.tkfentretenimento.meusdados.model.UserDAO;

import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.concurrent.Worker;
import javafx.concurrent.Worker.State;
import javafx.fxml.FXML;

public class Login extends WindowController{

	@FXML private WebView webview;

	@Override
	public void initialize(URL arg0, ResourceBundle arg1) {
		System.out.println(webview.getId());
		webview.getEngine().load("https://accounts.google.com/o/oauth2/auth?response_type=token&redirect_uri=http://localhost/meusdadoscallbacks/googlecallback.html&client_id=282550861704-ruv98no1oe9moimeh917fs31jtoc0mi7.apps.googleusercontent.com&scope="+Constants.SCOPES);
		webview.getEngine().getLoadWorker().stateProperty().addListener(new ChangeListener<State>() {
		     public void changed(ObservableValue ov, State oldState, State newState) {
		           if (newState == Worker.State.SUCCEEDED) {
		        	   	System.out.println(webview.getEngine().getLocation());
		                 if(webview.getEngine().getLocation().startsWith("http://localhost/meusdadoscallbacks/googlecallback.html")){
		                	String url = webview.getEngine().getLocation();
		     		    	String accessToken = url.substring(url.indexOf("=")+1, url.indexOf("&"));
		     		    	System.out.println("Acess Token: "+accessToken);
		     		    	try {
								new UserDAO(accessToken);
							} catch (ParseException e) {
								e.printStackTrace();
							} catch (SQLException e) {
								e.printStackTrace();
							}
		                 }
		           }
		     }
		});		
	}
	@Override
    public String getFXML() {
        return "/fxml/GoogleSignIn.fxml";
    }
    @FXML
    void ActionShow() {
        new Login()
                .setTitulo("Conectar-se")
                .show(getWindow()).altura(641).largura(818);
    }
    
    @FXML
    private void Close() {
        getWindow().close();
    }
}