I am using JAVA FXML GUI to parse a text file. The user can select which file to parse and then press "load". When the user clicks on "load" the file gets parse and many lines gets added to an ArrayList. The user then search and manipulate the text that was parse that is store in the ArrayList.
Sometimes while loading/writing the file to the ArrayList or manipulating some lines, the GUI is not responsive. How can I separate the GUI process vs. the ArrayList handling in order for the GUI to always be accessible to the user ?
The code below launches my application:
package javafxapp;
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;
public class Javafxapp extends Application {
#Override
public void start(Stage stage) throws Exception {
Parent root = FXMLLoader.load(getClass().getResource("FXMLDocument.fxml"));
Scene scene = new Scene(root);
stage.setScene(scene);
stage.show();
FXMLDocumentController controller = new FXMLDocumentController();
controller.openingSound();
}
/**
* #param args the command line arguments
*/
public static void main(String[] args) {
launch(args);
}
}
This is a textbook case for the use of multithreading.
See this JavaFX documentation for information and tutorials on how to begin using it.
Related
I'm trying to import an fxml file into my main class and Parent root = FXMLLoader.load(getClass().getResource(/View/Main_Form.fxml)); returns null.
It basically is telling me that it can't find the "Main_Form.fxml" file that I am asking it to find.
I have it in a package labeled "View" which is the path I specified.
code is as follows:
`package com.example.c482_1;
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;
public class HelloApplication extends Application {
#Override
public void start(Stage stage) throws Exception {
Parent root = FXMLLoader.load(getClass().getResource("/view/Main_Form.fxml"));
Scene scene = new Scene(root);
stage.setScene(scene);
stage.show();
}
public static void main(String[] args) {
launch();
}
}`
file structure of the project
I have tried checking the path, I made my main project the resource root with no luck as well.
Not quite sure but I would try checking to make sure the path is relative
I have a JavaFX in which the user can select files to be processed. Now I want to automate it so that you can run the application from the command line and pass those files as a parameter. I tried to do this:
java -jar CTester.jar -cl file.txt
public static void main(String[] args)
{
if (Arrays.asList(args).contains("-cl"))
{
foo();
}
else
{
launch(args);
}
}
The main is executed and the argument is correct, but this still creates the GUI.
From the docs:
The entry point for JavaFX applications is the Application class. The
JavaFX runtime does the following, in order, whenever an application
is launched:
Constructs an instance of the specified Application class
Calls the init() method
Calls the start(javafx.stage.Stage) method
Waits for the application to finish, which happens when either of the following
occur:
the application calls Platform.exit()
the last window has been closed and the implicitExit attribute on Platform is true
Calls the stop() method
So if I cannot use the main method, how can I create this "alterantive" flow? I thought about creating a normal java application as a wrapper but that seems a little bit overkill for such a simple task. Is there a more elegant way of doing this?
Simply exit the application after calling your foo() method:
Platform.exit();
Here is a quick sample application to demonstrate:
import javafx.application.Application;
import javafx.application.Platform;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
public class CLSample extends Application {
public static void main(String[] args) {
if (Arrays.asList(args).contains("-cl")) {
commandLine();
Platform.exit();
} else {
launch(args);
}
}
public static void commandLine() {
System.out.println("Running only command line version...");
}
#Override
public void start(Stage primaryStage) {
// Simple Interface
VBox root = new VBox(10);
root.setAlignment(Pos.CENTER);
root.setPadding(new Insets(10));
root.getChildren().add(new Label("GUI Loaded!"));
// Show the stage
primaryStage.setScene(new Scene(root));
primaryStage.setTitle("CLSample Sample");
primaryStage.show();
}
}
If you pass -cl, then only the commandLine() method gets called.
I am trying a build a small video player using java I am getting some errors,please help me fix them.
package sample;
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;
import javafx.scene.paint.Color;
public class Main extends Application {
#Override
public void start(Stage primaryStage) throws Exception{
Player player = new Player("/Users/name/Desktop/play.mp4");
Scene scene = new Scene(player, 720,480,Color.BLACK);
primaryStage.setScene(scene);
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
package sample;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.Pane;
import javafx.scene.media.Media;
import javafx.scene.media.MediaPlayer;
import javafx.scene.media.MediaView;
/**
* Created by akanksh on 03/11/17.
*/
public class Player extends BorderPane {
Media media;
MediaPlayer player;
MediaView view;
Pane mpane;
public Player(String file){
media = new Media(file);
player = new MediaPlayer(media);
view = new MediaView(player);
mpane = new Pane();
mpane.getChildren().add(view);
setCenter(mpane);
player.play();
}
}
errors :
No matter how many times I tried using different videos and different paths,its not working...help needed...
The media class needs a valid URI
Therefore you need a "schema" for your file such as file:///Users/...
Or you could use new File("/Users/name/Desktop/play.mp4").toURI()
The media constructor is looking for a URI, not a file path. If you are really specifying a file for the media (i.e. something the user specified on the file system, for example via a FileChooser) you should convert the path to a valid URI that both has a scheme and properly encodes any invalid characters in the path, such as whitespace.
If you have a File object, you simply do this with
File file = ... ;
Media media = new Media(file.toURI().toString());
If the file is specified as a string, create a file object first (though in any realistic situation you should have a File to begin with):
public Player(String file){
media = new Media(new File(file).toURI().toString());
player = new MediaPlayer(media);
view = new MediaView(player);
mpane = new Pane();
mpane.getChildren().add(view);
setCenter(mpane);
player.play();
}
Note that in the case where the media is part of the application (instead of being provided on the user's filesystem at run time), you should use a different technique entirely and treat it as a resource. See, for example, How to reference javafx fxml files in resource folder? for accessing resources in JavaFX.
I have an issue with JavaFX and multithreading. Basically I have an application and the task at hand asks me that I should have multiple users. Like for example I have a bug-testing application which shows a list of bugs and users and testers can choose to add/delete bugs from this list(a tableview in my case). Building the application was not a problem, but I don't understand how to 'simulate' multiple users. The task says that when I run my program, 3 windows should appear(2 for users and 1 for a tester), and when I add/delete a bug, the tableview should get updated.
I believe I need to do this with threads, as my last course involved multithreading, but I'm at a loss here. My main class looks like this:
import controller.OfertaCtrl;
import javafx.application.Application;
import javafx.application.Platform;
import javafx.fxml.FXMLLoader;
import javafx.scene.Scene;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.Pane;
import javafx.stage.Stage;
import repository.OfertaRepo;
import view.OfertaFXML;
import java.io.IOException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class Main extends Application {
private static Stage primaryStage;
private static Scene MyPage;
#Override
public void start(Stage primaryStage) throws Exception{
//Platform.setImplicitExit(false);
Main.primaryStage = primaryStage;
setPage();
}
public void setPage() throws IOException {
primaryStage.setTitle("Oferte");
FXMLLoader loader = new FXMLLoader(getClass().getResource("oferta.fxml"));
Pane pane = loader.load();
pane.setId("pane");
MyPage = new Scene(pane);
OfertaRepo repo = new OfertaRepo("C:\\Users\\Mihai\\workspace\\lalal\\newGUI\\src\\oferte.txt");
OfertaCtrl ctrl = new OfertaCtrl(repo);
OfertaFXML ctrl2 = loader.getController();
ctrl2.loadData(ctrl);
primaryStage.setScene(MyPage);
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
So basically I take a list of 'offers' in this example from a .txt file and put them in an ObservableArrayList with which I work with in my Controller class. The problem lies in the fact that I don't understand how I need to run multiple threads of the same application. Also, how would I update my tableview for all windows when I modify it in an open window? I was thinking of doing light pooling on my ObservableArrayList and checking for alterations every 1 second or so.
I can provide more information or whatever is needed, I just need a few points on how to go about solving this problem.
Here's how the application looks right now:
I've been looking at some blogs and other stackoverflow questions, and I'm not seeing a direct answer to my question. I am creating a javafx gui client and I want to have my menubar be one controller in one fxml and then i want the content area to be additional fxml files. The login screen will be one fxml, after the login screen will be the main content of the application and that will be in one fxml. How do i go about doing this?
I just don't want to have all of my code for my login, menubar, and main content in the same file. This is an image of what i am working on:
Use FXML as components by using a custom java class as fx:root and as fx:controller of your FXML file: http://docs.oracle.com/javafx/2/fxml_get_started/custom_control.htm
To do so, you need to call in the constructor of your custom java class FXMLLoader which will load your FXML.
The advantage is to change the way FXML load components.
The classic way to instanciate components via FXMLLoader with nested controllers is: FXML first, then controller for each part.
With this technique this is: controller first, then FXML for each component. And you won't load FXML in FXML directly, you will import your custom java classes in the FXML.
This is a better abstraction (no need to know how a component is implemented when you import them in FXML) and helps reusing code as it is like implementing a custom widget with FXML support. To make your component reusable, make sure your implementation doesn't have tight coupling with other parts, or use IOC to do so (for instance, with Spring integration with JavaFX). This way, you will be able to import your component in any part of your application (just like a DateInput widget) without worry and you won't duplicate code.
In your case you will have:
public class MenuBox extends VBox {
#FXML
private LoginBox loginBox;
#FXML
private ProfilesBox profilesBox;
public MenuBox() {
FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("menu.fxml"));
fxmlLoader.setRoot(this);
fxmlLoader.setController(this);
try {
fxmlLoader.load();
} catch (IOException exception) {
throw new RuntimeException(exception);
}
}
public class LoginBox extends VBox {
public LoginBox() {
FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("login.fxml"));
fxmlLoader.setRoot(this);
fxmlLoader.setController(this);
try {
fxmlLoader.load();
} catch (IOException exception) {
throw new RuntimeException(exception);
}
}
public class ProfilesBox extends VBox {
public ProfilesBox() {
FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("profiles.fxml"));
fxmlLoader.setRoot(this);
fxmlLoader.setController(this);
try {
fxmlLoader.load();
} catch (IOException exception) {
throw new RuntimeException(exception);
}
}
And you will import LoginBox and ProfilesBox in menu.fxml that manages the global layout for your page:
<?import com.foo.bar.LoginBox ?>
<?import com.foo.bar.ProfilesBox ?>
<fx:root type="javafx.scene.layout.VBox"
xmlns:fx="http://javafx.com/fxml">
<!-- Stuff here to declare the menu bar-->
<HBox>
<ProfilesBox fx:id="profilesBox"/>
<LoginBox fx:id="loginBox"/>
</HBox>
</fx:root>
login.fxml and profiles.fxml contain just basic components.
You can include FXML documents one within the other - this should help you with separating the design logic
This means you can have Nested Controllers - one for each document.
From the documentation, you can now setup your code such that logic can be separated as well as invoked from the root controller (if need be).
Hope that helps.
I needed a popup window with similar requirements (more control over the nodes and the layout).
Having worked my way through the recommendations, I found a solution that might be useful.
First, I created a second fxml document and second controller (in NetBeans, New -> Empty FXML ... -> Use Java Controller -> Create New ...).
A little challenging was to figure out how to build the stage in the main controller and connect it to the popup controller.
The link Passing Parameters JavaFX FXML gives some real good insights and techniques.
The final code looks like this (I hope it can help someone):
// Anchor Pane from the popup
#FXML
AnchorPane anchorPanePopup;
#FXML
private void soneButtonAction(ActionEvent event) throws IOException {
Stage newStage = new Stage();
AnchorPane anchorPanePopup = (AnchorPane) FXMLLoader.load(getClass().getResource("Popup_FXML.fxml"));
Scene scene = new Scene(anchorPanePopup);
newStage.setScene(scene);
newStage.initModality(Modality.APPLICATION_MODAL);
newStage.setTitle("Dialog Window");
newStage.showAndWait();
}
package javafxapplication11;
import java.io.IOException;
import java.net.URL;
import java.util.ResourceBundle;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.fxml.Initializable;
import javafx.scene.Node;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.CheckBox;
import javafx.stage.Stage;
public class FXMLDocumentController implements Initializable {
#FXML
private CheckBox c1;
#FXML
private CheckBox c2;
public void clicked1(ActionEvent e) throws IOException {
Parent home_page_parent
=FXMLLoader.load(getClass().getResource("AddDcuFXML.fxml"));
Scene home_page_scene = new Scene(home_page_parent);
Stage app_stage = (Stage) ((Node) e.getSource()).getScene().getWindow();
app_stage.hide(); //optional
app_stage.setScene(home_page_scene);
app_stage.show();
}
public void clicked2(ActionEvent e) throws IOException {
Parent home_page_parent
=FXMLLoader.load(getClass().getResource("ViewDCU.fxml"));
Scene home_page_scene = new Scene(home_page_parent);
Stage app_stage = (Stage) ((Node) e.getSource()).getScene().getWindow();
app_stage.hide(); //optional
app_stage.setScene(home_page_scene);
app_stage.show();
}
public void clicked3(ActionEvent e) throws IOException {
Parent home_page_parent
=FXMLLoader.load(getClass().getResource("ViewDCU.fxml"));
Scene home_page_scene = new Scene(home_page_parent);
Stage app_stage = (Stage) ((Node) e.getSource()).getScene().getWindow();
app_stage.hide(); //optional
app_stage.setScene(home_page_scene);
app_stage.show();
}
#Override
public void initialize(URL arg0, ResourceBundle arg1) {
// TODO Auto-generated method stub
}
}