JavaFX how to handle ActionEvent from controller class? - java

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);
}
}

Related

Access to Javafx elements from another class without FXML

I am using Javafx8 and lets say i have created many ui items (like buttons and so on...). I thought its a good idea to put all EventHandler for these buttons into a separates class. My question is: How can i get access from an EventHandler to any button, e.g. to diable it or to manipulate it on any other way.
Here is a minimum example with two buttons and a separate class for EventHandlers
Let's say this is my Start class:
public class App extends Application
{
#Override
public void start(Stage primaryStage) throws Exception {
Button b1 = new Button();
b1.setOnAction(ListenerClass.createB1Event());
Button b2 = new Button();
b2.setOnAction(ListenerClass.createB2Event());
VBox vbox = new VBox(b1, b2);
Scene scene = new Scene(vbox, 200, 200);
primaryStage.setTitle("App");
primaryStage.setScene(scene);
primaryStage.show();
}
public static void main( String[] args )
{
Application.launch(args);
}
}
And my (separate) listener class:
public class ListenerClass {
public static EventHandler<ActionEvent> createB1Event() {
return new EventHandler<ActionEvent>() {
public void handle(ActionEvent t) {
//Access here to b1 and b2...
//Deactivate B1
//Activate B2
}
};
}
public static EventHandler<ActionEvent> createB2Event() {
return new EventHandler<ActionEvent>() {
public void handle(ActionEvent t) {
//Access here to b1 and b2...
//Activate B1
//Dectivate B2
}
};
}
}
Thanks
So based on your principal. You want the button that is located in a vbox and got pressed to be disabled and all other buttons from that vbox to be enabled.
And your problem is how to find button that got pressed.
You need to use ActionEvent.getSource() method.
Heres how I'd code it....
This is Start class:
public class Main extends Application {
#Override
public void start(Stage primaryStage) throws Exception {
VBox vbox = new VBox();
Button b1 = addNewButton("Button1",vbox);
Button b2 = addNewButton("Button2",vbox);
Button b3 = addNewButton("Button3",vbox);
Scene scene = new Scene(vbox, 200, 200);
primaryStage.setTitle("App");
primaryStage.setScene(scene);
primaryStage.show();
}
public static Button addNewButton(String label, VBox ownerVBox){
Button button = new Button(label);
ownerVBox.getChildren().add(button);
button.setOnAction(ListenerClass.createBEvent());
return button;
}
public static void main(String[] args) {
launch(args);
}
}
Listener class:
public class ListenerClass {
public static EventHandler<ActionEvent> createBEvent() {
return new EventHandler<ActionEvent>() {
public void handle(ActionEvent t) {
Button b = (Button) t.getSource();
VBox vbox =(VBox) b.getParent();
vbox.getChildren().forEach(button-> {
button.setDisable(false);
});
b.setDisable(true);
}
};
}
}

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);
}
}

Using LauncherImpl.LAUNCH_MODE_JAR of LauncherImpl.launchApplication method in javafx

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

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);
}

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