Access property outside class - java

please see this code
import javafx.application.Application;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.ButtonBuilder;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;
public class Test extends Application {
private String pageTitle;
public static void main(String args[]) {
launch(args);
}
#Override
public void start(Stage stage) throws Exception {
this.setPageTitle("Hello World");
Button btn = ButtonBuilder.create()
.text("Test Button")
.onAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent actionEvent) {
// this handle should change the property if Test.pageTitle property
//this.setPageTitle("Change button");
System.out.println("Testing button action");
}
})
.build();
StackPane root = new StackPane();
root.getChildren().add(btn);
stage.setTitle(getPageTitle());
stage.setScene(new Scene(root, 400, 400));
stage.show();
}
public String getPageTitle() {
return pageTitle;
}
public void setPageTitle(String pageTitle) {
this.pageTitle = pageTitle;
}
}
I want every time is the button clicked, it will change the title of application.
How to make the event handler can access the property of Text class?

You should refer to current instance of Test class
Test.this.setPageTitle("Change button");

Related

Restart Javafx Application from other class? Application launch must not be called on the JavaFX Application Thread

Main Class :
package sample;
import javafx.application.Application;
import javafx.application.Platform;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.image.Image;
import javafx.stage.Stage;
import java.util.Objects;
public class Main extends Application {
private static Stage primaryStage;
#Override
public void start(Stage primaryStage) throws Exception {
Parent root = FXMLLoader.load(Objects.requireNonNull(getClass().getResource("sample.fxml")));
primaryStage.setTitle("Chess");
primaryStage.getIcons().add(new Image("sample/pieces/chessIcon.jpg"));
primaryStage.setScene(new Scene(root, 700, 600));
primaryStage.setResizable(false);
this.primaryStage = primaryStage;
primaryStage.show();
}
public static void restart() {
Platform.runLater(() -> {
primaryStage.close();
try {
Application.launch(Main.class);
} catch (Exception e) {
e.printStackTrace();
}
});
}
public static void main(String[] args) {
launch(args);
}
}
The Button Class(CheckMatePopUp) from where the application will be relaunched
package sample;
public class CheckMatePopUp implements Initializable {
#FXML
private Button closeBtn;
#FXML
private Label player;
#FXML
private void closeBtn(ActionEvent event){
System.exit(0);
}
#FXML
private void RestartBtn(ActionEvent event){
// Stage stage = (Stage) closeBtn.getScene().getWindow();
// stage.close();
Main.restart();
}
#Override
public void initialize(URL url, ResourceBundle resourceBundle) {
}
}
Getting error : java.lang.IllegalStateException: Application launch must not be called on the JavaFX Application Thread
at javafx.graphics#19/com.sun.javafx.application.LauncherImpl.launchApplication(LauncherImpl.java:173)
at javafx.graphics#19/com.sun.javafx.application.LauncherImpl.launchApplication(LauncherImpl.java:154)
at javafx.graphics#19/javafx.application.Application.launch(Application.java:236)
at sample.Main.lambda$restart$0(Main.java:33)
at javafx.graphics#19/com.sun.javafx.application.PlatformImpl.lambda$runLater$10(PlatformImpl.java:457)
at java.base/java.security.AccessController.doPrivileged(AccessController.java:399)
at javafx.graphics#19/com.sun.javafx.application.PlatformImpl.lambda$runLater$11(PlatformImpl.java:456)

How to open popup window from an other class without button click in javaFX?

So I've got a method called 'popup' in a javaFX controller class which opens a small popup window on top of the actual application window. This method runs without problem if it's assigned to a button in fxml and the button is clicked, but this is not the way I want to use it.
I've got an other class called 'Timer' with a new task (new thread) which is counting down from a certain number, and at a point it will open a popup window with a message. My purpose is to call and run the 'popup' method from this 'Timer' class. When I call the 'popup' method from here, it starts executing, but the popup window doesn't appear at all. (The method call happens as I get the message "in popup" on console from 'popup' method. )
So why does it work when a button click calls 'popup' method from the fxml file and why not when I call it from an other class? Thanks.
Please see the controller class with 'popup' method and the Timer class below (using Gradle in project):
"SceneController" controller class:
package GradleFX;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.fxml.Initializable;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Node;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.PasswordField;
import javafx.scene.layout.VBox;
import javafx.scene.paint.Color;
import javafx.scene.text.Text;
import javafx.stage.Modality;
import javafx.stage.Stage;
import java.io.IOException;
import java.net.URL;
import java.util.ResourceBundle;
//import java.awt.event.ActionEvent;
public class SceneController implements Initializable {
public static String password = "";
protected static int timercount = 20;
#FXML
private Label PWLabel;
#FXML
private Label bottomLabel;
#FXML
private PasswordField PWField;
#FXML
private Label showPWLabel;
protected static Label myBottomLabel;
private static PasswordField myPWField;
private static Label myShowPWLabel;
private static int tries;
#Override
public void initialize(URL location, ResourceBundle resources) {
Timer timerTask = new Timer();
myBottomLabel = bottomLabel;
myPWField = PWField;
myShowPWLabel = showPWLabel;
new Thread(timerTask).start();
}
**/***********************************************************************
/*This method runs if button is pressed in main application,
but can't make it work by calling it from Timer Class */
public void popup() {
System.out.println("in popup");
Stage dialogStage = new Stage();
dialogStage.initModality(Modality.WINDOW_MODAL);
VBox vbox = new VBox(new Text("Hi"), new Button("Ok."));
vbox.setAlignment(Pos.CENTER);
vbox.setPadding(new Insets(15));
dialogStage.setScene(new Scene(vbox));
dialogStage.show();
}
//****************************************************************************
public void showPW() {
myShowPWLabel.setText(myPWField.getText());
}
public void hidePW() {
myShowPWLabel.setText("");
}
public void exit() {
System.exit(0);
}
public void write() {
PWLabel.setText("Mukodik");
}
public void writeInput(String in) {
password = in;
System.out.println("final password text text: " + password);
writeFinally();
}
public void writeFinally() {
System.out.println("This is 'password' : " + password);
//bottomLabel.setText(password);
}
public void bottomLabelWrite() {
bottomLabel.setText(myPWField.getText());
}
public static void setLabel() throws InterruptedException {
myBottomLabel.setText("");
myBottomLabel.setText("Database has been permanently erased.");
//Thread.sleep(3000);
//System.exit(0);
}
public static void noKeyEnteredNote() {
myBottomLabel.setTextFill(Color.BLACK);
myBottomLabel.setText("No key entered. Type Main Key.");
}
public static void rightKey() {
myBottomLabel.setText("Yes, this is the right key.");
}
public static void wrongKey() throws InterruptedException {
tries = MasterKey.numOfTryLeft;
if (tries > 0) {
myBottomLabel.setTextFill(Color.RED);
myBottomLabel.setText("!!!Wrong key!!! You've got " + tries + " tries left!");
}
}
public void simpleTest(String in) {
System.out.println("in simpleTest and in is: " + in);
}
public void getMainKey() throws IOException, InterruptedException {
MasterKey masterKey = new MasterKey();
System.out.println("Inside SceneController");
masterKey.requestKey(myPWField.getText());
}
public void changeScreen(ActionEvent event) throws IOException, InterruptedException {
getMainKey();
if (MasterKey.isRightKey) {
Parent tableViewParent = FXMLLoader.load(getClass().getResource("Menu.fxml"));
Scene tableViewScene = new Scene(tableViewParent);
Stage window = (Stage) ((Node) event.getSource()).getScene().getWindow();
window.setScene(tableViewScene);
window.show();
}
}
}
This is Timer class:
package GradleFX;
import javafx.concurrent.Task;
import javafx.event.ActionEvent;
public class Timer extends Task {
private ActionEvent actionEvent;
#Override
protected Integer call() throws Exception {
boolean notCalled = true;
while (SceneController.timercount > 0) {
SceneController sceneController = new SceneController();
System.out.println(SceneController.timercount);
Thread.sleep(1000);
SceneController.timercount--;
if (SceneController.timercount < 19) {
System.out.println("Less than 5");
if(notCalled) {
sceneController.popup();
notCalled = false;
}
}
}
System.exit(0);
return null;
}
}
Add this to your code:
#Override
public void initialize(URL location, ResourceBundle resources) {
Timer timerTask = new Timer();
myBottomLabel = bottomLabel;
myPWField = PWField;
myShowPWLabel = showPWLabel;
new Thread(timerTask).start();
timerTask.setOnFinished(e->{
popup();
});
}

LinkedList erased in Action Handelers methods in JavaFX

I am working on an App that simulates an online shop for my Data Structures course, I am currently using JavaFX in the Eclipse IDE and Scene Builder for the GUI design, however I am trying to use a Double LinkedList to store the Accounts in the Sign In UI window, but for some reason every time that I try to insert a new Account object (in the Action Event method) into my List it doesn't inserts it, at least if I try to print it´s toString gives me a Null pointer Exception, but if the insert and the println is in the start method works. Last year a did an MP3 player using JavaFX but in Netbeans and I didn't use Scene Builder and the List did work, some one has any idea why is this happening?
package com.javafx.quvbi.controller;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.scene.Node;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.TextField;
import javafx.stage.Stage;
import javafx.scene.input.MouseEvent;
import java.io.IOException;
import javafx.application.Application;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
public class interfazController extends Application {
#FXML
private Button pausa, CreateAccBttn, LoginBttn;
#FXML
private TextField NameTF, AccountTF, PasswordTF, CardTF;
//Data
ListaDobleEnlazada<Account> accList;
public static void main(String[] args) {
launch(args);
}
#Override
public void start(Stage primaryStage) throws Exception {
// TODO Auto-generated method stub
//NameTF = new TextField();
//AccountTF = new TextField();
//PasswordTF= new TextField();
//CardTF = new TextField();
accList = new ListaDobleEnlazada<Account>();
//accList.insertarInicio(new Account("Diego","Qubi","22f24rf2",123321));
Parent root = FXMLLoader.load(getClass().getResource("/view/OptionUI.fxml"));
Scene scene = new Scene(root);
primaryStage.setScene(scene);
primaryStage.show();
System.out.println(accList.toString());
}
public ListaDobleEnlazada<Account> getAccounts() {
return accList;
}
#FXML
public void controlMusica(ActionEvent event) {
System.out.println("musica");
System.out.println(getAccounts().getInicio().toString());
}
public void CreateAccClick(MouseEvent event) throws IOException {
if(!NameTF.getText().isEmpty() && !AccountTF.getText().isEmpty() && !PasswordTF.getText().isEmpty() && !CardTF.getText().isEmpty()) {
accList.insertarInicio(new Account(NameTF.getText(), AccountTF.getText(), PasswordTF.getText(), Integer.parseInt(CardTF.getText())));
}
}
#SuppressWarnings("restriction")
public void createAccount(ActionEvent event) throws IOException {
if(!NameTF.getText().isEmpty() && !AccountTF.getText().isEmpty() && !PasswordTF.getText().isEmpty() && !CardTF.getText().isEmpty()) {
Parent loginUI = FXMLLoader.load(getClass().getResource("/view/GUI2.fxml"));
Scene logInScene = new Scene(loginUI);
Stage window = (Stage)((Node)event.getSource()).getScene().getWindow();
window.setScene(logInScene);
window.show();
System.out.println(NameTF.getText());
System.out.println(AccountTF.getText());
System.out.println(PasswordTF.getText());
System.out.println(CardTF.getText());
//this.accList.insertarInicio(new Account(NameTF.getText(), AccountTF.getText(), PasswordTF.getText(), Integer.parseInt(CardTF.getText())));
}
}
public void loginAccount(ActionEvent event) throws IOException {
Parent loginUI = FXMLLoader.load(getClass().getResource("/view/GUI2.fxml"));
Scene logInScene = new Scene(loginUI);
Stage window = (Stage)((Node)event.getSource()).getScene().getWindow();
window.setScene(logInScene);
window.show();
}
}

Managing different JavaFX stages through a signle slass

I'm writing a simple JavaFX application that has three Stages: Login, Register (Anmeldung) and Welcome (Anwendung). Sorry for the German namings!
I have created each Stage and it's Scene in an App class and the handling events in a Controller class and the designs in fxml files. I need to implement a MainApp class which has to manage the communication between Login, Anmeldung and Anwendung windows.
The MainApp should initially launch a Login window and then in there if the checkbox is selected, the MainApp should be notified and order the launch of Anmeldung window. After successful registration, the MainApp should close the Anmeldung window and show the Login window again. There, when user logs in, the MainApp should again close the Login window and order a launch for Anwendung window.
I have done the transition between Login and Anmeldung windows by modifying the LoginController, which shouldn't be done there and has to be accomplished via the MainApp.
Additionally the task wants the whole thing to be done with only one launch(args).
LoginController.java:
package controller;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.scene.Node;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.CheckBox;
import javafx.scene.control.PasswordField;
import javafx.scene.control.TextField;
import javafx.stage.Modality;
import javafx.stage.Stage;
import resources.Benutzer;
public class LoginController {
// private static MainApp mainApp;
#FXML
public TextField textFieldUserId;
#FXML
public PasswordField passwordFieldPasswort;
#FXML
public CheckBox checkBoxNeuAnmeldung;
#FXML
public Button buttonEinloggen;
private boolean neuAnmeldung = false;
// public void setCallBack(MainApp mainApp) {
// LoginController.mainApp = mainApp;
// }
#FXML
public void handleButtonEinloggenAction(ActionEvent event) throws Exception {
// Stage stage = (Stage) buttonEinloggen.getScene().getWindow();
if (neuAnmeldung == false) {
Benutzer benutzer = new Benutzer(textFieldUserId.getText(),
passwordFieldPasswort.getText());
Parent anwendungsScene = FXMLLoader
.load(getClass().getResource("/design/Anwendung.fxml"));
Stage anwendungsStage = new Stage();
((Node) (event.getSource())).getScene().getWindow().hide();
anwendungsStage.setScene(new Scene(anwendungsScene));
anwendungsStage.setTitle("Anmeldung");
anwendungsStage.show();
System.out.println(benutzer);
}
// stage.close();
System.out.println("Eingeloggt!");
}
#FXML
public void handleCheckBoxNeuAnmeldungAction(ActionEvent event)
throws Exception {
if (checkBoxNeuAnmeldung.isSelected()) {
neuAnmeldung = true;
Parent anmeldungsScene = FXMLLoader
.load(getClass().getResource("/design/Anmeldung.fxml"));
Stage anmeldungsStage = new Stage();
anmeldungsStage.initModality(Modality.WINDOW_MODAL);
anmeldungsStage
.initOwner(((Node) (event.getSource())).getScene().getWindow());
anmeldungsStage.setScene(new Scene(anmeldungsScene));
anmeldungsStage.setTitle("Anmeldung");
anmeldungsStage.show();
} else
neuAnmeldung = false;
System.out.println("Neu-Anmeldung? " + neuAnmeldung);
}
}
AnmeldungsController.java:
package controller;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.scene.control.Button;
import javafx.scene.control.PasswordField;
import javafx.scene.control.TextField;
import javafx.stage.Stage;
import resources.Benutzer;
public class AnmeldungsController {
// private static MainApp mainApp;
#FXML
public TextField textFieldUserId;
#FXML
public PasswordField passwordFieldPasswort;
#FXML
public PasswordField passwordFieldWiederholung;
#FXML
public Button buttonAnmelden;
// public void setCallBack(MainApp mainApp) {
// AnmeldungsController.mainApp = mainApp;
// }
#FXML
public void handleButtonAnmeldenAction(ActionEvent event) {
Stage stage = (Stage) buttonAnmelden.getScene().getWindow();
if (passwordFieldPasswort.getText()
.equals(passwordFieldWiederholung.getText())) {
Benutzer benutzer = new Benutzer(textFieldUserId.getText(),
passwordFieldPasswort.getText());
System.out.println(benutzer);
System.out.println("Angemeldet!");
stage.close();
} else {
textFieldUserId.setText("Passwörter stimmen nicht überein!");
System.out.println("Passwörter stimmen nicht überein!");
System.out.println(passwordFieldPasswort.getText() + " != "
+ passwordFieldWiederholung.getText());
}
}
}
AnwendungsController.java:
package controller;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.scene.control.Button;
import javafx.stage.Stage;
public class AnwendungsController {
// private static MainApp mainApp;
#FXML
public Button buttonSchliessen;
// public void setCallBack(MainApp mainApp) {
// AnwendungsController.mainApp = mainApp;
// }
#FXML
public void handleButtonAbbrechenAction(ActionEvent event) {
Stage stage = (Stage) buttonSchliessen.getScene().getWindow();
stage.close();
System.out.println("Fenster Geschlossen!");
}
}
MainApp.java:
package application;
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;
public class MainApp extends Application {
public static void main(String[] args) {
launch(args);
}
#Override
public void start(Stage primaryStage) throws Exception {
FXMLLoader loader = new FXMLLoader(
getClass().getResource("/design/Login.fxml"));
Parent root = loader.load();
primaryStage.setTitle("Benutzerverwaltung");
primaryStage.setScene(new Scene(root));
primaryStage.show();
}
}
Of course the other aspects of the program like Exceptions and creating/reading/deleting users etc is out of the scope of this question!
Here is the basic idea that should get you started:
public class LoginController {
private final ReadOnlyBooleanWrapper loggedIn = new ReadOnlyBooleanWrapper();
public ReadOnlyBooleanProperty loggedInProperty() {
return loggedIn.getReadOnlyProperty() ;
}
public final boolean isLoggedIn() {
return loggedInProperty().get();
}
#FXML
public TextField textFieldUserId;
#FXML
public PasswordField passwordFieldPasswort;
#FXML
public CheckBox checkBoxNeuAnmeldung;
#FXML
public Button buttonEinloggen;
private boolean neuAnmeldung = false;
#FXML
public void handleButtonEinloggenAction(ActionEvent event) throws Exception {
// assuming you verify the login credentials...
loggedIn.set(true);
System.out.println("Eingeloggt!");
}
}
and now in your MainApp you can do:
package application;
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;
public class MainApp extends Application {
public static void main(String[] args) {
launch(args);
}
#Override
public void start(Stage primaryStage) throws Exception {
FXMLLoader loader = new FXMLLoader(
getClass().getResource("/design/Login.fxml"));
Parent root = loader.load();
LoginController loginController = loader.getController();
loginController.loggedInProperty().addListener((obs, wasLoggedIn, isNowLoggedIn) -> {
if (isNowLoggedIn) {
// user is now logged in, show welcome screen...
}
});
primaryStage.setTitle("Benutzerverwaltung");
primaryStage.setScene(new Scene(root));
primaryStage.show();
}
}

JavaFX TextField EventHandler

Currently I have a TextField which is my address bar and a WebView which is my page. When I click ented the TextField doesn't seem to do anything. It's meant to run the loadPage method and set to page to load whatever the user entered into the address bar. Any help would be appreciated.
package javafx_webview;
import javafx.application.Application;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.scene.Scene;
import javafx.scene.control.TextField;
import javafx.scene.layout.StackPane;
import javafx.scene.web.WebEngine;
import javafx.scene.web.WebView;
import javafx.stage.Stage;
public class Main extends Application {
WebEngine myWebEngine;
public static void main(String[] args) {
launch(args);
}
public void start(Stage primaryStage) {
primaryStage.setTitle("Platinum v1");
TextField addressBar = new TextField();
addressBar.setOnAction(new EventHandler<ActionEvent>() {
public void handle(ActionEvent event) {
loadPage(event.toString());
}
});
WebView myBrowser = new WebView();
myWebEngine = myBrowser.getEngine();
StackPane root = new StackPane();
root.getChildren().add(myBrowser);
root.getChildren().add(addressBar);
primaryStage.setScene(new Scene(root, 640, 480));
primaryStage.show();
}
private void loadPage(String url) {
try {
myWebEngine.load(url);
} catch (Exception e) {
System.out.println("The URL you requested could not be found.");
}
}
}
Get the url to load from the text of the address bar, not the toString of the action event on the address bar.
final TextField addressBar = new TextField();
addressBar.setOnAction(new EventHandler<ActionEvent>() {
public void handle(ActionEvent event) {
myWebEngine.load(addressBar.getText());
}
});
Also the load is asynchronous, so your exception handler won't work. You need to monitor's the webengine loadworker's exception property to get exceptions from the engine. Also note that a url not found is not necessarily an exception which would be reported, instead a web server will usually return a page for a http 404 error.
Here is a working sample:
import javafx.application.Application;
import javafx.beans.value.*;
import javafx.event.*;
import javafx.scene.Scene;
import javafx.scene.control.TextField;
import javafx.scene.layout.VBox;
import javafx.scene.web.*;
import javafx.stage.Stage;
public class Main extends Application {
private WebEngine myWebEngine;
public void start(Stage stage) {
stage.setTitle("Platinum v1");
final TextField addressBar = new TextField();
addressBar.setOnAction(new EventHandler<ActionEvent>() {
public void handle(ActionEvent event) {
myWebEngine.load(addressBar.getText());
}
});
WebView myBrowser = new WebView();
myWebEngine = myBrowser.getEngine();
myWebEngine.getLoadWorker().exceptionProperty().addListener(new ChangeListener<Throwable>() {
#Override public void changed(ObservableValue<? extends Throwable> observableValue, Throwable oldException, Throwable exception) {
System.out.println("WebView encountered an exception loading a page: " + exception);
}
});
VBox root = new VBox();
root.getChildren().setAll(
addressBar,
myBrowser
);
stage.setScene(new Scene(root));
stage.show();
}
public static void main(String[] args) { launch(args); }
}

Categories