Using LauncherImpl.LAUNCH_MODE_JAR of LauncherImpl.launchApplication method in javafx - java

I have my main class
public class Main {
public static void main(String args[])
{
String cur_dir = System.getProperty("user.dir");
cur_dir += "\\AppTest.jar";
System.out.println("Jar path="+cur_dir);
LauncherImpl.launchApplication(cur_dir, LauncherImpl.LAUNCH_MODE_JAR, args);
}
}
My Application class
public class AppTest extends Application {
#Override
public void start(Stage stage) throws Exception {
FXMLLoader loader = new FXMLLoader(getClass().getResource(
"FXMLDocument.fxml"));
Parent root=loader.load();
FXMLDocumentController controller=loader.getController();
controller.setMyInstance(controller);
Scene scene = new Scene(root);
//Platform.setImplicitExit(true);
stage.setScene(scene);
stage.setOnHidden(new EventHandler<WindowEvent>() {
#Override
public void handle(WindowEvent event) {
controller.thread.stop();
}
});
stage.show();
}
}
But it's not working
I followed this post
I want to run the latest jar of the application kind of auto update

Related

JavaFX how to handle ActionEvent from controller class?

Hello i have problem with handling action from my button: here's my code:
public class HelloWorld extends Application {
Button btn;
#Override
public void start(Stage primaryStage) {
btn = new Button();
btn.setText("Say 'Hello World'");
StackPane root = new StackPane();
root.getChildren().add(btn);
Scene scene = new Scene(root, 300, 250);
primaryStage.setTitle("Hello World!");
primaryStage.setScene(scene);
primaryStage.show();
}
public void setButtonOnAction(EventHandler<ActionEvent> acn)
{
btn.setOnAction(acn);
}
}
my controller class
public class Controller {
private HelloWorld helloWorld;
private Model model;
public Controller(HelloWorld helloWorld, Model model) throws Exception {
this.helloWorld = helloWorld;
this.model = model;
System.out.println(this.mainView.returnOne());
this.helloWorld.setButtonOnAction(e->
{
System.out.println("CATCH");
});
}
}
main runClass:
public class runExample {
public static void main(String[] args) throws Exception {
HelloWorld helloWorld = new HelloWorld();
Model model = new Model();
Application.launch(helloWorld.getClass(),args);
Controller controller = new Controller(helloWorld, model);
}
}
`
Does anyone know why setButtonOnAction don't work in controller class but in HelloWorld class it work perfectly ? Compiler don't give me any error. Only if i switch in run class like that:
Controller controller = new Controller(mainView, model);
Application.launch(mainView.getClass(),args);
it gives me
Exception in thread "main" java.lang.NullPointerException
and if i'm using setButtonOnAction in HelloWorld class it works fine. Can u help me catch event in my controller class ? I'm using jdk8 but on 11 it isn't work too.
Working example ;)
public class HelloWorld extends Application {
Button btn;
#Override
public void start(Stage primaryStage) {
btn = new Button();
btn.setText("Say 'Hello World'");
StackPane root = new StackPane();
root.getChildren().add(btn);
Scene scene = new Scene(root, 300, 250);
Controller controller = new Controller(this,new Model()));
primaryStage.setTitle("Hello World!");
primaryStage.setScene(scene);
primaryStage.show();
}
public void setButtonOnAction(EventHandler<ActionEvent> acn)
{
btn.setOnAction(acn);
}
}
And run class:
public class runExample {
public static void main(String[] args) throws Exception {
Application.launch(HelloWorld.class,args);
}
}

How to get JavaFX to display API feed

My question is pretty straight forward (I'm just a recreational coder playing around with stuff). I have established a connection to an API and via the magic of RxJava I can subscribe to the json data emitted the API . I have also created a very basic GUI using FXML.
How do I make the text within TextArea = textAreaA update every time an event is emitted via subscription? Said differently, how do I make the TextArea display the API feed?
I've read the RxJavaFx-guide from cover to cover and it seems to focus more on the Fx to Rx directional flow of events :(
Here is a sample of my code:
public class Tester extends Application{
private static final Logger LOG = LoggerFactory.getLogger(Tester.class);
public static void main(String[] args) throws IOException, InterruptedException{
launch(args);
}
public void start (Stage primaryStage) throws Exception {
FXMLLoader loader = new FXMLLoader(getClass().getResource("sample.fxml"));
Parent root = loader.load();
primaryStage.setTitle("App Window");
primaryStage.setScene(new Scene(root, 300, 275));
primaryStage.show();
TESTER_API.TESTER_API_Connector();
}
}
public class TESTER_API {
public static void TESTER_API_Connector() throws IOException, InterruptedException {
StreamingEvents emissions = StreamingEventsFactory.INSTANCE.createEvents(TheseStreamingEvents.class.getName());
emissions.connect().blockingAwait();
emissions.getEvents().getSomethingSpecific()
.subscribe(event -> System.out.println(event.getSomethingSpecific()) // Here is the event that I would like to bind or otherwise push to textAreaA in the FXML controller
,throwable -> new Exception("GUI error!"));
}
}
public class FXMLDocumentController implements Initializable {
#FXML
public TextArea textAreaA;
#Override
public void initialize(URL arg0, ResourceBundle arg1) {
// TODO Auto-generated method stub
}
}
My idea was to make TESTER_API call a function in FXMLDocumentController that updates textAreaA. I would recommend using Platform.runLater() to enshure thread safety.
public class Tester extends Application{
[...]
public void start (Stage primaryStage) throws Exception {
FXMLLoader loader = new FXMLLoader(getClass().getResource("sample.fxml"));
Parent root = loader.load();
FXMLDocumentController controller = loader.getController();
primaryStage.setTitle("App Window");
primaryStage.setScene(new Scene(root, 300, 275));
primaryStage.show();
TESTER_API.TESTER_API_Connector(controller);
}
}
public class TESTER_API {
public static void TESTER_API_Connector(FXMLDocumentController controller) throws IOException, InterruptedException {
[...]
emissions.getEvents().getSomethingSpecific()
.subscribe(event -> Platform.runLater(() -> {
controller.updateTextArea(event.getSomethingSpecific());
}),
throwable -> new Exception("GUI error!"));
}
}
public class FXMLDocumentController implements Initializable {
#FXML
public TextArea textAreaA;
[...]
public void updateTextArea(String string) {
textAreaA.setText(string);
}
}

java.lang.reflect.InvocationTargetException when calling method from FXML

I am working on a fairly simple program but I can't figure out what is wrong here. This is my Main class:
public class Main extends Application {
private QualityList ql;
private QualityController controller;
private Stage primaryStage;
#Override
public void start(Stage stage) throws Exception {
primaryStage = stage;
Parent root = FXMLLoader.load(getClass().getResource("/controller/QualityWindow.fxml"));
primaryStage.setTitle("Kwaliteiten V1.0");
primaryStage.setScene(new Scene(root, 1250, 800));
primaryStage.show();
ql = new QualityList();
controller = new QualityController();
controller.initController(ql);
controller.setStage(primaryStage);
ql.addObserver(controller);
}
public static void main(String[] args) {
launch(args);
}
}
This is my controller class (The parts I am having trouble with):
private QualityList ql;
private Stage stage;
private DBClass connect;
public void initController(QualityList ql){
this.ql=ql;
this.connect = new DBClass();
readData();
initialiseTable();
}
.
.
.
#FXML
void printData(ActionEvent event){
ql.printData();
}
The problem I am having is that when calling upon the method printData through the interface with an event it will cause an java.lang.reflect.InvocationTargetException.
However when calling to the same method from for example the initController method it will run exactly as planned.
This problem also only seems to present itself when the original ql object is made in the main class and passed to the controller.
If I make the ql object in the controller itself there are no problems but then I cannot observe the ql object.
I did the initialisation of my controller wrong. this is the richt way to do it:
#Override
public void start(Stage primaryStage) throws Exception {
ql = new QualityList();
this.primaryStage = primaryStage;
FXMLLoader loader = new FXMLLoader();
loader.setLocation(getClass().getResource("/controller/QualityWindow.fxml"));
Parent root = loader.load();
QualityController controller = loader.getController();
//Parent root = FXMLLoader.load(getClass().getResource("/controller/QualityWindow.fxml"));
primaryStage.setScene(new Scene(root, 1250, 800));
primaryStage.setTitle("Kwaliteiten V1.0");
primaryStage.show();
controller.initController(ql);
ql.addObserver(controller);
}
public static void main(String[] args) {
launch(args);
}

JavaFX fireEvent StackOverflowError

I'm currently working on a little game with JavaFX, and i had some problems to catch keyEvents.
Now i can catch them but the program throw a java.lang.StackOverflowError and it didn't do what I expected when a key is pressed.
Here is the main class:
public class WarbladeFX extends Application {
Game root;
public void start(Stage primaryStage) {
root = new Game();
Scene scene = new Scene(root, 800, 600);
scene.setFill(new Color(0,0,0,1));
scene.setOnKeyPressed(new EventHandler<KeyEvent>() {
public void handle(KeyEvent event) {
Event.fireEvent(root, event);
}
});
scene.setOnKeyReleased(new EventHandler<KeyEvent>() {
public void handle(KeyEvent event) {
Event.fireEvent(root, event);
}
});
primaryStage.setTitle("WarbladeFX");
primaryStage.setScene(scene);
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
And the Game class:
public class Game extends Group {
Entity ship;
long delta;
HashSet<String> input = new HashSet<>();
public Game() {
File f = new File("src/ressources/ship.gif");
ship = new Entity(new Image("file:///" + f.getAbsolutePath().replace("\\", "/")) ,300, 300);
getChildren().add(ship);
setOnKeyPressed(new EventHandler<KeyEvent>() {
#Override
public void handle(KeyEvent event) {
//System.out.println(".handle()");
String code = event.getCode().toString();
if(!input.contains(code))
input.add(code);
}
});
setOnKeyReleased(new EventHandler<KeyEvent>() {
#Override
public void handle(KeyEvent event) {
String code = event.getCode().toString();
input.remove(code);
}
});
new AnimationTimer(){
#Override
public void handle(long now) {
if(input.contains("LEFT"))
ship.setVelX(-1);
if(input.contains("RIGHT"))
ship.setVelX(1);
ship.move(now);
getChildren().clear();
getChildren().add(ship);
}
}.start();
}
}
Some help would be very great.
Events fired on nodes in the scene graph will "bubble up" to the parent, and then the parent of the parent, and eventually all the way up to the scene. So the event handlers that you defined on the scene "refire" the event to the root, which will then bubble up to the scene and get handled again, being refired again to the root, and so on...
If you want to catch the events anywhere in the scene, and then handle them in the Game class, define some methods in Game to process the events and invoke those methods. Don't "refire" the events.
For example:
public class Game extends Group {
Entity ship;
long delta;
HashSet<String> input = new HashSet<>();
public Game() {
File f = new File("src/ressources/ship.gif");
ship = new Entity(new Image("file:///" + f.getAbsolutePath().replace("\\", "/")) ,300, 300);
getChildren().add(ship);
new AnimationTimer(){
#Override
public void handle(long now) {
if(input.contains("LEFT"))
ship.setVelX(-1);
if(input.contains("RIGHT"))
ship.setVelX(1);
ship.move(now);
getChildren().clear();
getChildren().add(ship);
}
}.start();
}
public void keyDown(String key) {
if(!input.contains(key))
input.add(key);
}
public void keyUp(String key) {
input.remove(code);
}
}
and then you can do
public class WarbladeFX extends Application {
Game root;
public void start(Stage primaryStage) {
root = new Game();
Scene scene = new Scene(root, 800, 600);
scene.setFill(new Color(0,0,0,1));
scene.setOnKeyPressed(new EventHandler<KeyEvent>() {
public void handle(KeyEvent event) {
game.keyDown(event.getCode().toString());
}
});
scene.setOnKeyReleased(new EventHandler<KeyEvent>() {
public void handle(KeyEvent event) {
game.keyUp(event.getCode().toString());
}
});
primaryStage.setTitle("WarbladeFX");
primaryStage.setScene(scene);
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
you are generating an infinite loop when you fire the event again in the event-handle method. Try to handle the event in this method, i.e. react to the users input.

How to call all of the methods of a class in a method of another class in java

I am designing a JavaFX application and I need to call the Application class of one of the windows in the Controller of another window.
MainController.java:
public class MainController {
#FXML
public Button buttonLogin;
#FXML
public Button buttonNeuAnmelden;
#FXML
public void handleButtonLoginAction(ActionEvent event) {
((Node) (event.getSource())).getScene().getWindow().hide();
System.out.println("LoginButton geclickt!");
}
#FXML
public void handleButtonNeuAnmeldenAction(ActionEvent event) {
((Node) (event.getSource())).getScene().getWindow().hide();
System.out.println("NeuAnmeldenButton Geclickt!");
}
}
LoginApp.java:
public class LoginApp 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();
}
}
I specifically need to run all of the methods of LoginApp, meaning main(String[] args) and start(Stage primaryStage) class in handleButtonLoginAction() method as if the whole class as it is has been called exactly at that point.
How do I do this?
If I understand the question correctly, you need to refactor this quite a bit. Define a LoginView class that is independent of your Application subclass:
public class LoginView {
private final Stage displayStage ;
private final Scene scene ;
public LoginView(Stage displayStage) throws IOException {
this.displayStage = displayStage ;
FXMLLoader loader = new FXMLLoader(
getClass().getResource("/design/Login.fxml"));
Parent root = loader.load();
scene = new Scene(root);
displayStage.setScene(scene);
displayStage.setTitle("Benutzerverwaltung");
}
public LoginView() throws IOException {
this(new Stage());
}
public void show() {
displayStage.show();
}
public void hide() {
displayStage.hide();
}
// ...
}
and then your Application class looks like:
public class LoginApp extends Application {
#Override
public void start(Stage primaryStage) throws IOException {
LoginView loginView = new LoginView(primaryStage);
// ...
loginView.show();
}
}
Your question didn't show how MainController is related to the application, but all you need to do is pass a reference to the loginView you created to the MainController, and then call loginView.show() from the method in the MainController.

Categories