How to get JavaFX to display API feed - java

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

Related

How to register EventBus only once

I'm writing JavaFX application in order to send from one controller to other controller. I use EventBus which was written by developer. I download it from github.But When I try to recall from one controller to other controller. First time it works once. Second time it works twice. Third time it works three times and so on. What might be reason of behaving this eventbus?
MainController
here Event bus was registered like static
public class Main extends Application
{
public static EventBus eventBus = new FxEventBus();
#Override
public void start(Stage primaryStage) throws Exception{
Parent root = FXMLLoader.load(getClass().getResource("sample.fxml"));
primaryStage.setTitle("Hello World");
primaryStage.setScene(new Scene(root));
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
This controller class which was fired event
Controller
private AddClickedEvent addClickedEvent;
#Override
public void initialize(URL location, ResourceBundle resources)
{
id.setOnAction(event ->
{
try
{
FXMLLoader loader = new FXMLLoader();
Parent parent = loader.load(getClass().getResource("ask.fxml").openStream());
Stage stage = new Stage();
stage.setScene(new Scene(parent));
if(addClickedEvent == null){
addClickedEvent = new AddClickedEvent(AddClickedEvent.ANY);
}
Main.eventBus.fireEvent(addClickedEvent);
stage.showAndWait();
} catch (IOException e) {
e.printStackTrace();
}
});
}
Here is Controller other Controller that should show up something after fire
#Override
public void initialize(URL location, ResourceBundle resources)
{
Main.eventBus.addEventHandler(AddClickedEvent.ANY,event -> {
System.out.println("uyondan bosilib galdi");
System.out.println(yes);
yes = true;
});
id1.setOnAction(event -> {
System.out.println(yes);
});
id2.setOnAction(event -> {
Stage stage = (Stage)((Node) (event).getSource()).getScene().getWindow();
stage.close();
});
}
AddClicked Event class
public class AddClickedEvent extends Event
{
public static final EventType<AddClickedEvent> ANY =
new EventType<>(Event.ANY, "ADD_CLIENT_EVENT");
public AddClickedEvent(#NamedArg("eventType") EventType<? extends Event> eventType) {
super(eventType);
}
}
EventHandler should be created only once in process of whole application then it will react only once rather than multiple times. I come up with solutions to it declare for every controller class with static int variable which helps me to register events only once when the value of int is zero.
private static int check;
#Override
public void initialize(URL location, ResourceBundle resources)
{
if(check == 0)
{
Main.eventBus.addEventHandler(AddClickedEvent.ANY,event -> {
System.out.println("uyondan bosilib galdi");
System.out.println(yes);
yes = true;
});
check ++;
// Then it will react only once We registered event here
}
id1.setOnAction(event -> {
System.out.println(yes);
});
id2.setOnAction(event -> {
Stage stage = (Stage)((Node) (event).getSource()).getScene().getWindow();
stage.close();
});
}

How do I access a public String that's initialized in my Main Class from an FXML Controller [duplicate]

This question already has answers here:
Passing Parameters JavaFX FXML
(10 answers)
Closed 4 years ago.
In my main class I have
public class Main extends Application {
public static void main(String[] args) {
launch(args);
}
public String versionNumber = "v2.1";
#Override
public void start(Stage primaryStage) throws Exception{
// SETTING UP THE STAGE
Stage window;
window = primaryStage;
window.setTitle("Support Tool " + versionNumber);
// SETTING UP THE SCENES
Parent parentNewCallDetails = FXMLLoader.load(getClass().getResource("newCallDetails.fxml"));
Scene scnNewCallDetails = new Scene (parentNewCallDetails, 800, 600);
// CHOOSING THE SCENE AND SHOWING THE STAGE
window.setScene(scnNewCallDetails);
window.show();
}
}
I essentially want to be able to access String versionNumber from within the following code in my FXML controller where I set the title of the next scene that I'm launching
public class newCallController {
// ACTION COMPLETED WHEN CALL BUTTON IS PRESSED
public void btnCall(MouseEvent event) throws IOException {
// TODO LAUNCH THE NEXT CALL WINDOW
Parent fxmlMainCallWindow = FXMLLoader.load(getClass().getResource("mainCallWindow.fxml"));
Scene scnMainCallWindow = new Scene(fxmlMainCallWindow, 1000, 800);
Stage window = (Stage)((Node)event.getSource()).getScene().getWindow();
// THIS IS WHERE I WANT TO ACCESS THE VERSIONNUMBER STRING
window.setTitle("Support Tool " + versionNumber);
window.setScene(scnMainCallWindow);
}
}
You can define a Constants class with static string param. You can use it anywhere. Like: Constants.VERSION
public class Constants {
public static final String VERSION = "v2.1";
}

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