JavaFX ImageView image not showing - java

I have an assets folder full of images to implement in a game I'm creating and I want to display these in the window. This is my code so far.
public class javafxtest extends Application {
public void start(Stage primaryStage) throws Exception {
Group root = new Group();
Scene scene = new Scene(root, 600, 600);
Image test = new Image("file:assets/BA.png");
ImageView piece = new ImageView(test);
piece.setX(10);
piece.setY(10);
Rectangle rct = new Rectangle(50, 150, 500, 300);
rct.setFill(Color.GRAY);
root.getChildren().addAll(rct, piece);
primaryStage.setScene(scene);
primaryStage.show();
}
}
This will be for a program to run within IntelliJ/from a jar. The assets folder is in the same directory as this file. I get no file path error so I assume it can find the image, but it doesn't appear on screen and the rectangle does.
Fair warning, I'm learning JavaFX from scratch and I'm finding there's not much explanation as to how things work, so this could be a stupid question.

Accessing the image via the filesystem is the wrong choice when the image is in fact an asset (ie it is distributed along side the .class files that make up your program) because that way you'd have to deal with the installation path (otherwise known as the home path). The correct choice is bundling your image in your JAR, so place your image in the following path:
src/main/resources/assets/BA.png
and access it with:
Image test = new Image("/assets/BA.png");
This is how the file tree should look like in your computer:

Related

How to make Java save my background image in extracted, compiled java program?

When I try to run my extracted/compiled java program I can see pictures cause they are stored on my PC and addressed in the code from my PC. But when I try the same program on another PC, pictures/backgrounds are gone.
How to store pictures into java code while I'm calling them from a disk into ImageView so they are viewable on other systems too ?
I am using JavaFX and FXML, CSS.
You can bundle your images with java program using two ways:
1) put them inside your jar - create a package named eg. "images" and add the images there, then load it using
BufferedImage img = ImageIO.read(getClass().getResourceAsStream("/images/image.jpg"));
2) put them in to the same folder as your jar and load them with:
BufferedImage img = ImageIO.read(new File("image.jpg"));
For you the best way is probably the #1 because youll get just one jar - it is easier to copy such jar and harder to tamper the images.
I've done it like this. Thanks!
#Override
public void start(Stage stage) throws Exception
{
Parent root = FXMLLoader.load(getClass().getResource("/grafika.fxml"));
Scene scene = new Scene(root);
scene.getStylesheets().add("/application.css");
Image picture1 = new Image("/kava.jpg");
ImageView slika1 = new ImageView(picture1);
slika1.setImage(picture1);
stage.setScene(scene);
stage.setMaxHeight(530);
stage.setMaxWidth(800);
stage.setResizable(false);
stage.show();
}

How can I make a full screen java application?

I have an image viewer appplication. It works perfectly, but I'd like to make a full screen mode for it. It's an FXML project in Netbeans so, the main java is a separated file, therefore I cannot use this:
stage.setFullScreen(true);
because I can't reach the stage from my main .java file.
So I have a file, its name is imageViewer.java, it has this:
public void start(Stage stage) throws Exception {
Parent root = FXMLLoader.load(getClass().getResource("image_view.fxml"));
Scene scene = new Scene(root);
String css = this.getClass().getResource("style.css").toExternalForm();
scene.getStylesheets().add(css);
stage.setMinHeight(640);
stage.setMinWidth(960);
stage.setScene(scene);
stage.show();
}
and I have another file, it has fxml implements, and the ActionEvent void methods, you know, click the button, next picture etc...
The mentioned method (start method above) it's a method, therefore I can't return the stage. I have to reach the stage from image_viewController.java (the main java), what includes the other methods, functions and FXML implements etc...
I'd like to do this:
public void fullScreen(ActionEvent e) {
stage.setFullScreen(true);
}
But I can't reach the stage from another .java file. This is the first problem. And the second problem.
How can I make position absolute my panes, Vboxes etc like in html??? If my ImageView (what contains my image) get the full width and height, pulls down my HBox (what includes the buttons). If HBox were in absolute position, it wouldn't happened this, would it?
And the final problem, how can I make that, my HBox doesn't appear, just triggered by a hover effect. Is it possible with a separated css file? As I know, it is possible to make with FXML files.
Thanks for the answers!

Import STL file in JavaFX

My problem is that I am trying to import a 3D model from an STL file to a JavaFX application. I followed the code in this link How to create 3d shape from STL in JavaFX 8? and it's only working with the jewel file mentioned there, but I've tried with other STL files and it's not working!
I can't see why it's not working with the other files. Can anyone explain this?
Any help please, as soon as possible!
As you are already using an STL importer from this site, you will find in the same web a 3D model browser you can use to preview your models before importing them to your JavaFX application.
If they can't be imported with this browser, the problem may be related to a non valid STL format in your files.
If they are imported, then the problem may be in your application. Embed the call in a try-catch and post the exception you may enconter.
StlMeshImporter stlImporter = new StlMeshImporter();
try {
stlImporter.read(this.getClass().getResource("<STLfile>.stl"));
}
catch (ImportException e) {
e.printStackTrace();
return;
}
EDIT
If no exception is thrown while reading the model, the next step would be inserting the returned mesh into a MeshView and show it on our scene:
TriangleMesh mesh = stlImporter.getImport();
stlImporter.close();
MeshView mesh=new MeshView(cylinderHeadMesh);
Group root = new Group(mesh);
Scene scene = new Scene(root, 1024, 800, true);
Camera camera = new PerspectiveCamera();
scene.setCamera(camera);
primaryStage.setScene(scene);
primaryStage.show();
Since the model could be too small or too big for our scene (related to the camera and the point of view we are using), we should print the bounding box of our model, and then scale it up or down accordingly:
System.out.println("mesh: "+mesh.getBoundsInLocal().toString());
mesh.setScaleX(1d);
mesh.setScaleY(1d);
mesh.setScaleZ(1d);
Or we could change the camera parameters:
double max = Math.max(mesh.getBoundsInLocal().getWidth(),
Math.max(mesh.getBoundsInLocal().getHeight(),
mesh.getBoundsInLocal().getDepth()));
camera.setTranslateZ(-3*max);

JavaFX Application Icon

Is it possible to change the application icon using JavaFX, or does it have to be done using Swing?
Assuming your stage is "stage" and the file is on the filesystem:
stage.getIcons().add(new Image("file:icon.png"));
As per the comment below, if it's wrapped in a containing jar you'll need to use the following approach instead:
stage.getIcons().add(new Image(<yourclassname>.class.getResourceAsStream("icon.png")));
Full program for starters :) This program sets icon for StackOverflowIcon.
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.image.Image;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;
public class StackoverflowIcon extends Application {
#Override
public void start(Stage stage) {
StackPane root = new StackPane();
// set icon
stage.getIcons().add(new Image("/path/to/stackoverflow.jpg"));
stage.setTitle("Wow!! Stackoverflow Icon");
stage.setScene(new Scene(root, 300, 250));
stage.show();
}
public static void main(String[] args) {
launch(args);
}
}
Output Screnshot
Updated for JavaFX 8
No need to change the code. It still works fine. Tested and verified in Java 1.8(1.8.0_45). Path can be set to local or remote both are supported.
stage.getIcons().add(new Image("/path/to/javaicon.png"));
OR
stage.getIcons().add(new Image("https://example.com/javaicon.png"));
Hope it helps. Thanks!!
I tried this and it totally works. The code is:
stage.getIcons().add(
new Image(
<yourclassname>.class.getResourceAsStream( "icon.png" )));
icon.png is under the same folder as the source files.
If you have have a images folder and the icon is saved in that use this
stage.getIcons().add(new Image(<yourclassname>.class.getResourceAsStream("/images/comparison.png")));
and if you are directly using it from your package which is not a good practice use this
stage.getIcons().add(new Image(<yourclassname>.class.getResourceAsStream("comparison.png")));
and if you have a folder structure and you have your icon inside that use
stage.getIcons().add(new Image(<yourclassname>.class.getResourceAsStream("../images/comparison.png")));
you can add it in fxml. Stage level
<icons>
<Image url="#../../../my_icon.png"/>
</icons>
stage.getIcons().add(new Image(<yourclassname>.class.getResourceAsStream("/icon.png")));
If your icon.png is in resources dir and remember to put a '/' before otherwise it will not work
What do you think about creating new package i.e image.icons in your src directory and moving there you .png images? Than you just need to write:
Image image = new Image("/image/icons/nameOfImage.png");
primaryStage.getIcons().add(image);
This solution works for me perfectly, but still I'm not sure if it's correct (beginner here).
stage.getIcons().add(new Image(ClassLoader.getSystemResourceAsStream("images/icon.png")));
images folder need to be in Resource folder.
stage.getIcons().add(new Image(<yourclassname>.class.getResourceAsStream("/icon.png" )));
You can add more than one icon with different sizes using this method.The images should be different sizes of the same image and the best size will be chosen.
eg. 16x16, 32,32
You can easily put icon to your application using this code line
stage.getIcons().add(new Image("image path") );
stage.getIcons().add(new Image("/images/logo_only.png"));
It is good habit to make images folder in your src folder and get images from it.
I used this in my application
Image icon = new Image(getClass().getResourceAsStream("icon.png"));
window.getIcons().add(icon);
Here window is the stage.
If you run the jar file, the code specified by Michael Berry will change the icon in the title bar and in the taskbar. Shortcut icon cannot be changed.
If you run a native program compiled with com.zenjava, You must add a link to the program icon:
<plugin>
<groupId>com.zenjava</groupId>
<artifactId>javafx-maven-plugin</artifactId>
<version>8.8.3</version>
<configuration>
...
<bundleArguments>
<icon>${project.basedir}/src/main/resources/images/filename.ico</icon>
</bundleArguments>
</configuration>
</plugin>
This will add an icon to the shortcut and taskbar.
Toggle icons in runtime:
In addition to the responses here, I found that once you have assigned an Icon to your application by the first time you cannot toggle it by just adding a new icon to your stage (this would be helpful if you need to toggle the icon of your app from on/off enabled/disabled).
To set a new icon during run time use the getIcons().remove(0) before trying to add a new icon, where 0 is the index of the icon you want to override like is shown here:
//Setting icon by first time (You can do this on your start method).
stage.getIcons().add(new Image(getClass().getResourceAsStream("enabled.png")));
//Overriding app icon with a new status (This can be in another method)
stage.getIcons().remove(0);
stage.getIcons().add(new Image(getClass().getResourceAsStream("disabled.png")));
To access the stage from other methods or classes you can create a new static field for stage in you main class so can access it from out of the start() method by encapsulating in on a static method that you can access from anywhere in your app.
public class MainApp extends Application {
private static Stage stage;
public static Stage getStage() { return stage; }
#Override public void start(Stage primaryStage) {
stage = primaryStage
stage.getIcons().add(new Image(getClass().getResourceAsStream("enabled.png")));
}
}
public class AnotherClass {
public void setStageTitle(String newTitle) {
MainApp.getStage().setTitle(newTitle);
MainApp.getStage().getIcons().remove(0);
MainApp.getStage().getIcons().add(new Image(getClass().getResourceAsStream("disabled.png")));
}
}
If you got Invalid URL or resource not found put your icon.png in the "bin" folder in your workspace.
Another easy way to insert your own icon on the title bar in JavaFX is to add the image to your primary stage using the following method:
Image ico = new Image("resources/images/iconLogo.png");
stage.getIcons().add(ico);
Make sure your import javafx.scene.image.Image (if using an ide like netbeans this should be automatically done for you).
I tried this and it works:
stage.getIcons().add(new Image(getClass().getResourceAsStream("../images/icon.png")));

Animated Splash Screen on Netbeans Platform app

Our maven/Netbeans platform application uses a custom image on startup, by replacing
Nbm-branding > core.jar > org.netbeans.core.startup > splash.gif
I tried making it an animated .gif, but only the first frame is displayed.
How would one possibly go about implementing an animated splash screen, maybe by running some JavaFX window animations?
I've seen another other SO question, but it wasn't really answered - please notice I'm asking about how to integrate a custom splash screen with my Netbeans Platform application, and not how to actually build it.
Surprisingly enough, I found out how to plug in a custom splash screen based on this post about user authentication and authorization.
Basically, one needs to write another start-up class, instead of the platform's default:
import java.lang.reflect.Method;
public class CustomStartup {
private static final String NB_MAIN_CLASS = "org.netbeans.core.startup.Main";
public static void main(String[] args) throws Exception {
// do whatever you need here (e.g. show a custom login form)
System.out.println("Hello world! I am a custom startup class");
JWindow splash = initSplash();
// once you're done with that, hand control back to NetBeans
ClassLoader classloader = Thread.currentThread().getContextClassLoader();
Class<?> mainClass = Class.forName(NB_MAIN_CLASS, true, classloader);
Object mainObject = mainClass.newInstance();
Method mainMethod = mainClass.getDeclaredMethod("main", new Class[]{String[].class});
mainMethod.invoke(mainObject, (Object) args);
splash.setVisible(false);
}
}
In that class, one can create a JavaFX stage, embed it into a JWindow, and show it:
public JWindow initSplash(){
JWindow window = new JWindow();
final JFXPanel fxPanel = new JFXPanel();
window.add(fxPanel);
window.setVisible(true);
window.setLocationRelativeTo(null);
Platform.runLater(new Runnable() {
#Override
public void run() {
Scene scene = new Scene(new CustomFxSplash(), 475, 300, true);
fxPanel.setScene(scene);
}
}
return window;
}
Other things to remember are:
Suppress the original NetBeans splash screen by running your app with the --nosplash parameter.
Call your custom initialization class by running your app with the -J-Dnetbeans.mainclass=com.package.splash.CustomStartup parameter
As the link suggests this custom class has to be on the platform's initialization classpath, meaning inside the platform/core folder.
The current version of the NetBeans class that is responsible for rendering the splash screen can be viewed online here: org.netbeans.core.startup.
The culprit code that prevents the gif from animating is this line (line 546)
graphics.drawImage(image, 0, 0, null);
In order for the gif to animate the ImageObserver will have to be specified instead of being set to null and then repaint must be called when imageUpdate() is called on the ImageObserver.
An example of displaying an animated gif can be viewed here: Relationship Between Animated Gif and Image Observer
So as far as I can see you will either have to change the above NetBeans platform code and rebuild it for your application or you will have to create your own splash screen from scratch to use instead of the NetBeans one.
Hope you find this useful!

Categories

Resources