JavaFX missing Legend class - java

I have this code:
List<Node> legends = new ArrayList<>(lineChart.lookupAll("Label.chart-legend-item"));
Legend legend1 = (Legend)legends.get(0);
The problem is that my IDE can't find any Legend class to import it.
I'm talking about this class: https://docs.oracle.com/javafx/2/api/javafx/scene/doc-files/cssref.html#legend
I'm using Java 10. Why my IDE don't find Legend class?
What I want to achieve is to take the name of legend.

It looks like Legend is from an internal api:
import com.sun.javafx.charts.Legend;
Probably removed in Java9+

You have export the module com.sun.javafx.charts to access the Legend class as the Legend class is part of the internal API.
In IntelliJ you have to add an override to the compiler:
(Settings -->Build, Execution, Deployment --> Compiler --> Java compiler -->Override compiler parameters)
--add-exports=javafx.controls/com.sun.javafx.charts=ALL-UNNAMED
And in the run configuration add to the VM Options.
The import is:
import com.sun.javafx.charts.Legend;
Edit: It has not been removed as the accepted answer says.
Example code:
import com.sun.javafx.charts.Legend;
import javafx.application.Application;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.scene.Scene;
import javafx.scene.layout.AnchorPane;
import javafx.stage.Stage;
public class Main extends Application {
public static void main(String[] args) {
Application.launch(args);
}
#Override
public void start(Stage primaryStage) throws Exception {
Legend legend = new Legend();
Legend.LegendItem legendItem = new Legend.LegendItem("Test legend item");
ObservableList<Legend.LegendItem> items = FXCollections.observableArrayList(legendItem);
legend.setItems(items);
AnchorPane anchorPane = new AnchorPane(legend);
Scene scene = new Scene(anchorPane, 400, 600);
primaryStage.setScene(scene);
primaryStage.show();
}
}
And to compiler options add:
If you use gradle you have to add the compiler option to the build.gradle too.
compileJava {
options.compilerArgs += ["--add-exports=javafx.controls/com.sun.javafx.charts=ALL-UNNAMED"]
}

TilePane is super class of Legend.
So you can cast to TilePane.
List<Node> legends = new ArrayList<>(lineChart.lookupAll("Label.chart-legend-item"));
TilePane legend1 = (TilePane) legends.get(0);
legend1.setHgap(10);
legend1.getChildren().remove(..);
...

Related

I'm trying to import an fxml file into my main class and Parent root = FXMLLoader.load(getClass().getResource()); returns null

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

Couldn't find or load main class in JavaFx sample [duplicate]

I'm trying to build a small user interface using JavaFX, But I'm getting an error like this:
Error: Could not find or load main class myApp Caused by:
java.lang.NoClassDefFoundError: javafx/application/Application
This is my code:
and im using jdk 12.0.2
import javafx.application.Application;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.paint.Color;
import javafx.stage.Stage;
public class myApp extends Application{
public static void main(String[] args) {
Phonebook mybook = new Phonebook();
launch(args);
}
#Override
public void start(Stage primaryStage) throws Exception {
Group group = new Group();
Scene scene = new Scene(group, 600, 300);
scene.setFill(Color.GRAY);
primaryStage.setTitle("Phone Book");
primaryStage.setScene(scene);
primaryStage.show();
}
This is the Libraries and jdk I'm using:
Image1
I think JavaFX is not a part of the JDK > 9 any more. (Your version is 12.x.x)
Probably this could help you:
https://openjfx.io/openjfx-docs/#install-javafx
(Assuming you are using Maven) If this does not help, try to clean and build your Application.
Sometimes Maven does not recognize newly added dependencies.

Executing a new JavaFX application on a separate JVM

I'm trying to launch a new process on a separate JVM via code following the method illustrated here:
Executing a Java application in a separate process
The code I'm using is the following (taken from the question above):
public static int exec(Class klass) throws IOException, InterruptedException {
String javaHome = System.getProperty("java.home");
String javaBin = javaHome +
File.separator + "bin" +
File.separator + "java";
String classpath = System.getProperty("java.class.path");
String className = klass.getName();
ProcessBuilder builder = new ProcessBuilder(javaBin,"-cp",classpath,className);
Process process = builder.inheritIO().start();
process.waitFor();
return process.exitValue();
}
...in which klass is the class I want to launch.
This would work for a normal Java process, but the problem is that I'm trying to launch a JavaFX application, and the code above generates the following error:
Error: JavaFX runtime components are missing, and are required to run this application
So, to add the JavaFX modules, I tried including the --module-path and --add-modules commands in the declaration of builder, I even attempted copying and pasting the entire execution command, and I kept getting this other error:
Unrecognized option: (command string with modules)
Error: Could not create the Java Virtual Machine.
Error: A fatal exception has occurred. Program will exit.
How could I solve this?
Let me know if details are needed.
Since the advent of modules, there are at least three different ways a JavaFX application can be configured:
Put everything on the module-path, including the JavaFX modules and your module.
This is the ideal situation but not always possible/viable (e.g. because of incompatible dependencies).
Put the JavaFX modules on the module-path and your own code on the class-path.
This configuration requires the use of --add-modules.
Put everything on the class-path, including the JavaFX modules and your own code.
With this configuration your main class cannot be a subtype of Application. Otherwise you get the error you mentioned in your question: "Error: JavaFX runtime components are missing, and are required to run this application".
This configuration allows for easy use of so-called fat/uber JARs.
Warning: This approach is explicitly unsupported.
The command line used with ProcessBuilder will depend on which configuration your application uses. You also have to take into account any other options passed the command line, such as the default encoding or locale. Unfortunately, your question doesn't provide enough information to tell what exactly is going wrong. The error you mention makes me think you're using the third configuration, but I can't be sure.
That said, I'll give some examples of launching the same application from within the application; you should be able to modify things to fit your needs. Note I used Java/JavaFX 13.0.1 when testing the below code.
Configuration #1
Put everything on the module-path.
module-info.java:
module app {
requires javafx.controls;
exports com.example.app to
javafx.graphics;
}
Main.java:
package com.example.app;
import java.io.IOException;
import java.io.UncheckedIOException;
import java.nio.file.Path;
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;
import static java.lang.System.getProperty;
public class Main extends Application {
private static void launchProcess() {
try {
new ProcessBuilder(
Path.of(getProperty("java.home"), "bin", "java").toString(),
"--module-path",
getProperty("jdk.module.path"),
"--module",
getProperty("jdk.module.main") + "/" + getProperty("jdk.module.main.class"))
.inheritIO()
.start();
} catch (IOException ex) {
throw new UncheckedIOException(ex);
}
}
#Override
public void start(Stage primaryStage) {
Button launchBtn = new Button("Launch process");
launchBtn.setOnAction(
event -> {
event.consume();
launchProcess();
});
primaryStage.setScene(new Scene(new StackPane(launchBtn), 500, 300));
primaryStage.setTitle("Multi-Process Example");
primaryStage.show();
}
}
Command line:
java --module-path <PATH> --module app/com.example.app.Main
Replace "<PATH>" with a path containing both the JavaFX modules and the above module.
Configuration #2
Put JavaFX modules on the module-path and your code on the class-path.
Main.java:
package com.example.app;
import java.io.IOException;
import java.io.UncheckedIOException;
import java.nio.file.Path;
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;
import static java.lang.System.getProperty;
public class Main extends Application {
private static void launchProcess() {
try {
new ProcessBuilder(
Path.of(getProperty("java.home"), "bin", "java").toString(),
"--module-path",
getProperty("jdk.module.path"),
"--add-modules",
"javafx.controls",
"--class-path",
getProperty("java.class.path"),
Main.class.getName())
.inheritIO()
.start();
} catch (IOException ex) {
throw new UncheckedIOException(ex);
}
}
#Override
public void start(Stage primaryStage) {
Button launchBtn = new Button("Launch process");
launchBtn.setOnAction(
event -> {
event.consume();
launchProcess();
});
primaryStage.setScene(new Scene(new StackPane(launchBtn), 500, 300));
primaryStage.setTitle("Multi-Process Example");
primaryStage.show();
}
}
Command line:
java --module-path <M_PATH> --add-modules javafx.controls --class-path <C_PATH> com.example.app.Main
Replace "<M_PATH>" with a path containing the JavaFX modules and replace "<C_PATH>" with a path containing the above code.
Configuration #3
Put everything on the class-path. Note the main class (now Launcher) is not a subclass of Application.
Launcher.java:
package com.example.app;
import javafx.application.Application;
public class Launcher {
public static void main(String[] args) {
Application.launch(Main.class, args);
}
}
Main.java:
package com.example.app;
import java.io.IOException;
import java.io.UncheckedIOException;
import java.nio.file.Path;
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;
import static java.lang.System.getProperty;
public class Main extends Application {
private static void launchProcess() {
try {
new ProcessBuilder(
Path.of(getProperty("java.home"), "bin", "java").toString(),
"--class-path",
getProperty("java.class.path"),
Launcher.class.getName())
.inheritIO()
.start();
} catch (IOException ex) {
throw new UncheckedIOException(ex);
}
}
#Override
public void start(Stage primaryStage) {
Button launchBtn = new Button("Launch process");
launchBtn.setOnAction(
event -> {
event.consume();
launchProcess();
});
primaryStage.setScene(new Scene(new StackPane(launchBtn), 500, 300));
primaryStage.setTitle("Multi-Process Example");
primaryStage.show();
}
}
Command line:
java --class-path <PATH> com.example.app.Launcher
Replace "<PATH>" with a path containing the JavaFX JARs and the above code.

Multithreading in JavaFX same application

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:

How to keep Java FXML active while file is loading

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.

Categories

Resources