Understanding getSystemResource() in Java - java

How can I access the icon.png file without specifing the whole path "main/res/images/icon.png" in ClassLoader.getSystemResource()? I wanted something like images/icon.png.
This is the project explorer
Main.java:
package main.java.OOP20.alt.sim.View;
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;
import javafx.scene.image.Image;
import java.awt.*;
public class Main extends Application {
public static final double PROPORTION = 1.5;
#Override
public void start(final Stage primaryStage) throws Exception {
final Dimension dimension = java.awt.Toolkit.getDefaultToolkit().getScreenSize();
final double width = dimension.getWidth() / PROPORTION;
final double height = dimension.getHeight() / PROPORTION;
final Parent root=FXMLLoader.load(
ClassLoader.getSystemResource("main/res/layouts/sample.fxml")
);
primaryStage.setTitle("Title");
primaryStage.setScene(new Scene(root, width, height));
primaryStage.getIcons().add(
new Image(ClassLoader.getSystemResource("main/res/images/icon.png").toString())
);
primaryStage.show();
}
public static void main(final String[] args) {
launch(args);
}
}

You can get url of both fxml or png files with using Class<T>#getResource(). You should use following solutions:
For fxml file:
Parent root = FXMLLoader.load(getClass().getResource("/layouts/sample.fxml"));
For png file:
primaryStage.getIcons().add(new Image(getClass().getResource("/images/icon.png").toString()));
Note: If you want to load any external resources (fxml, png etc) from resource folder within static methods, you must use Main.class.getClass() instead of getClass(). It guarantees the resource will be loaded relative to that class, and never relative to a subclass.

Related

How do I write the path to a FXML file in my JavaFX application?

I'm trying to write the path in the main class to load a FXML file MenuFXML.fxml but I can't figure out the correct way to do so. The FXML file is in the package com.developer.fxml and the main class is in com.developer.
I've already tried the path /com/developer/fxml/MenuFXML.fxml and /fxml/MenuFXML.fxml but neither of them work.
package com.developer;
import com.developer.exit.ExitApplication;
import com.developer.util.css.AddCSS;
import java.io.IOException;
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;
public class Main extends Application {
private Stage stage;
private Scene scene;
private final String title = "Stock Program 2.0";
private Parent root;
private final AddCSS addcss = new AddCSS();
#Override
public void start(Stage primaryStage) throws IOException {
stage = primaryStage;
stage.setTitle(title);
stage.setOnCloseRequest(e -> {
e.consume();
ExitApplication ep = new ExitApplication();
ep.closeProgram(stage);
});
//The part that I can't get to work
root = FXMLLoader.load(getClass().getResource("/fxml/MenuFXML.fxml"));
scene = new Scene(root);
addcss.setStylesheet(scene);
stage.setScene(scene);
stage.show();
}
/**
* #param args the command line arguments
*/
public static void main(String[] args) {
launch(args);
}
}

why setImage() doesn't change my ImgView in JavaFx?

import javafx.application.Application;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.AnchorPane;
import javafx.scene.layout.Pane;
import javafx.scene.layout.TilePane;
import javafx.stage.Stage;
public class ChooseScheme extends Application{
GUIBoard board = new GUIBoard();
Stage primaryStage;
Integer totalScheme = 26;
//these are the imgs I want to change, in the fxml file they have their own path but with the method chooseRandomImgs(),
#FXML
ImageView scheme1 = new ImageView();
#FXML
ImageView scheme2 = new ImageView();
#FXML
ImageView scheme3 = new ImageView();
#FXML
ImageView scheme4 = new ImageView();
public void launchChooseScheme() throws Exception {
start(new Stage());
}
//standard method, it runs and open the scene
#Override
public void start(Stage primaryStage) throws Exception {
this.primaryStage = primaryStage;
Parent ChooseScheme;
ChooseScheme = FXMLLoader.load(getClass().getClassLoader().getResource("GUIFiles/ChooseScheme.fxml"));
Stage stage = new Stage();
chooseRandomImgs();
stage.setTitle("Choose Scheme");
stage.setScene(new Scene(sgChooseScheme, 600, 400));
stage.show();
}
//this method should change my img
private void chooseRandomImgs() {
int countImages = totalScheme;
int imageNumber = (int) (Math.random() * countImages);
System.out.println(imageNumber);
Image schemeImage = new Image("GUIfiles/imgs/schemecard/val5/"+ imageNumber + ".jpg");
scheme1.setImage(schemeImage);
}
}
The Img path is correct. When I run the class doesn't change the ImgView scheme1; instead it remains the Img I set on SceneBuilder, every time I run the code never shows the new Img. I don't understand why.
The instance of ChooseScheme is a different one than the one that is used with the fxml (assuming the fx:controller attribute is set to the appropriate value).
You always initialize the ImageView fields, but if the instance of ChooseScheme is not used with a fxml, the instances are never added to a scene. (In fact the instances created by the initializer are never added to a scene, but for the controller used with a fxml the initial values are replaced during load.)
It is never a good idea to initialize fields that are supposed to be injected from the fxml. This just fixes the NullPointerException that may be thrown.
Using the Application class as controller is not a good idea either.
Depending on where you want to determine the random images, you need to use one of the approaches presented here Passing Parameters JavaFX FXML .
Alternatively you could do this from the initialize method of the controller. This method is run during load after all objects have been injected.
Example
Controller class
package mypackage;
...
public ChooseSchemeController {
private static final Random random = new Random();
private static final int TOTAL_SCHEME = 26; // you don't want to use a wrapper type here
#FXML
private ImageView scheme1;
#FXML
private void initialize() {
chooseRandomImage(scheme1);
}
private void chooseRandomImage(ImageView iv) {
int imageNumber = random.nextInt(TOTAL_SCHEME);
System.out.println(imageNumber);
Image schemeImage = new Image("GUIfiles/imgs/schemecard/val5/"+ imageNumber + ".jpg");
iv.setImage(schemeImage);
}
}
GUIFiles/ChooseScheme.fxml
<VBox xmlns:fx="http://javafx.com/fxml/1" fx:controller="mypackage.ChooseSchemeController">
<children>
<ImageView fx:id="scheme1"/>
</children>
</VBox>

Trouble setting application icon with JavaFX

I am having trouble changing the application icon with JavaFX (code is below with my attempts commented out). I tried implementing several solutions from previous stack overflow answers but I'm not sure if those methods are now deprecated. I am using NetBeans 8.2 (and the icon is in a folder called images under the source package).
1st Attempt: Illegal start of expression. identifier expected: JavaFX Application Icon
2nd Attempt: No suitable method found for add(java.awt.Image): Changing the icon of my java application
3rd Attempt: Cannot find symbol. Cannot instantiate the type Image java?
5th Attempt: Image is abstract it cannot be instantiated. http://docs.oracle.com/javafx/2/deployment/self-contained-packaging.htm
package javafxapplication1;
import java.awt.Image;
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;
import javafx.stage.StageStyle;
import javafx.event.EventHandler;
import javafx.scene.input.MouseEvent;
import javax.imageio.ImageIO;
public class JavaFXApplication1 extends Application {
private double xOffset = 0;
private double yOffset = 0;
#Override
public void start(Stage stage) throws Exception {
//stage.getIcons().add(Image(<JavaFXApplication1>.class.getResourceAsStream( "/images/fiji.png" ));
Image i = ImageIO.read(getClass().getResource("/images/fiji.png"));
//setIconImage(i);
//stage.getIcons().add(i);
//stage.getIcons().add(Image("/images/fiji.png"));
// stage.getIcons().add(ImageIO.read(getClass().getResource("/images/fiji.png")));
//stage.getIcons().add(new Image(this.getClass().getResourceAsStream("/images/fiji.png")));
Parent root = FXMLLoader.load(getClass().getResource("FXMLDocument.fxml"));
//stage.initStyle(StageStyle.UNDECORATED);
// makes it moveble
// LOOK INTO!!!!!!!!!!!
root.setOnMousePressed(new EventHandler<MouseEvent>() {
#Override
public void handle(MouseEvent event) {
xOffset = event.getSceneX();
yOffset = event.getSceneY();
}
});
root.setOnMouseDragged(new EventHandler<MouseEvent>() {
#Override
public void handle(MouseEvent event) {
stage.setX(event.getScreenX() - xOffset);
stage.setY(event.getScreenY() - yOffset);
}
});
Scene scene = new Scene(root);
stage.setScene(scene);
stage.show();
}
/**
* #param args the command line arguments
*/
public static void main(String[] args) {
launch(args);
}
}
You need to load an Image and add it to the stage's icons.
import javafx.scene.image.Image;
Image icon = new Image(Controller.class.getResource("/game.png").toExternalForm(), false);
primaryStage.getIcons().add(icon);
However, on Ubuntu these icons do not get displayed. This JavaFX defect hasn't been solved for a long time.
It seems that your first attempt is missing the new keyword for the Image instantiation, and make sure it is a javafx.scene.image.Image, not a java.awt.Image image, which has a different constructor. Try this:
stage.getIcons().add(new Image(JavaFXApplication1.class.getResource( "/images/fiji.png" ).toExternalForm());
First, load an image and then add to the stage object. Please make sure to give path starting from the inside of the resource folder, not from the resource folder, or else use the whole project path.
Image favicon = new Image('URL_OF_THE_IMAGE');
stage.getIcons.add(favicon);

Why the items I add to my ObservableList are only accessible from the function they are declared

Context
I just started to learn JavaFX so I'm developing a program to discover it. The program I'm on needs a array, so I used ObservableList. But here is the problem, the items I add to the list are only accessible from the function itself.
Here is the situation :
package fr.cartes;
import fr.cartes.model.MapModel;
import fr.cartes.view.ListMapsController;
import javafx.application.Application;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.fxml.FXMLLoader;
import javafx.scene.Scene;
import javafx.stage.Stage;
import java.io.IOException;
import java.util.ArrayList;
public class MainApp extends Application {
private Stage primaryStage;
private ObservableList<MapModel> maps = FXCollections.observableArrayList();
public static void main(String[] args){
launch(args);
}
public void start(Stage primaryStage) throws Exception {
this.primaryStage = primaryStage;
this.primaryStage.setTitle("/!\\ Explorateur /!\\");
this.primaryStage.setAlwaysOnTop(true);
initializationOfProgram();
}
public void initializationOfProgram(){
initializeListMaps();
maps.add(new MapModel("Les Etats-Unis d'Amérique", "EU.jpg"));
maps.add(new MapModel("La France d'aujourdh'ui", "FR.jpg"));
for(MapModel mapModel : maps){
System.out.println(mapModel.getMapName());
}
}
public void initializeListMaps(){
for(MapModel map : maps){
System.out.println(map.getMapName());
}
try {
FXMLLoader loader = new FXMLLoader();
loader.setLocation(MainApp.class.getResource("view/ListMaps.fxml"));
Scene scene = new Scene(loader.load());
primaryStage.setScene(scene);
primaryStage.show();
ListMapsController controller = new ListMapsController();
controller.setMainApp(this);
controller.loadMapsOnListView(maps);
}catch(IOException exception){exception.printStackTrace();}
}
public ObservableList<MapModel> getMapsLists(){
return maps;
}
}
For example, if I put a println() test in the initializationOfProgram(), I will have "Les Etats-Unis d'Amérique" and "La France d'aujourd'hui" written on the console, but if I do this println() test in initializeListMaps(), it won't display anything.
Am I missing something obvious here ? Can you help me ?

Cannot find symbol error when calling method from different class file

I'm trying to call a method form a separate class file to my main program java file but when I try to call the method on an object, I get the error symbol cannot be found for the method. Both files are in the same directory.
//This is my main java file for the program
package pwmanager;
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;
/**
*
* #author 176878
*/
public class PWManager extends Application {
#Override
public void start(Stage stage) throws Exception {
Parent root = FXMLLoader.load(getClass().getResource("Login.fxml"));
Scene scene = new Scene(root);
stage.setScene(scene);
stage.setTitle("Password Manager");
stage.setPrevStage(); //Error occurs here.
stage.show();
}
/**
* #param args the command line arguments
*/
public static void main(String[] args) {
launch(args);
}
}
//This is the other .java file where the method is declared.
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package pwmanager;
import java.io.IOException;
import java.net.URL;
import java.util.ResourceBundle;
import javafx.event.ActionEvent;
import javafx.event.EventType;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.fxml.Initializable;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.control.*;
import javafx.scene.layout.AnchorPane;
import javafx.scene.layout.GridPane;
import javafx.stage.Stage;
import javax.xml.crypto.Data;
/**
*
* #author 176878
*/
public class FXMLDocumentController implements Initializable {
#FXML
private Button loginButton;
private Button addAcct;
private Button removeAcct;
#FXML
public Stage prevStage;
public Stage currentStage;
#FXML
public void loginButtonAction(ActionEvent event) throws IOException {
System.out.println("You clicked me, logging in!");
Stage stage = new Stage();
FXMLLoader loader = new FXMLLoader(getClass().getResource("MainScreen.fxml"));
Parent mainScreen = (Parent)loader.load();
Scene scene = new Scene(mainScreen);
stage.setScene(scene);
stage.setTitle("Password Manager");
//prevStage.close();
stage.show();
}
#FXML
public void addAcctAction(ActionEvent event) throws IOException {
System.out.println("You clicked me, adding account!");
}
#FXML
public void removeAcctAction(ActionEvent event) throws IOException {
System.out.println("You clicked me, removing account!");
}
#Override
public void initialize(URL url, ResourceBundle rb) {
// TODO
}
}
I need to store the current stage so I can call it back or close the stage out.
setPrevStage is defined in FXMLDocumentController not Stage. You need to inject the former into the main PWManager class so that it can be invoked
controller.setPrevStage(stage);

Categories

Resources