Stuck in the basics. I have some syntax issues setting up the Image Path.
When i try to create an Image and give it the image path, it always throws some some exception about the path. I have commented out some of the path combination I have already tryed. Can you please tell me what I am doing wrong? Thank you.
package jopofx;
public JoPoCTRL(JoPoFX gui){
this.gui = gui;
}
public void updateImages(){
Image img = null;
try{
//img = new Image("C:\\Users\\ ... //FullPath ... \\JoPoFX\\src\\jopofx\\myimage.png");
img = new Image("\\JoPoFX\\src\\jopofx\\myimage.png");
//img = new Image("\\src\\jopofx\\myimage.png");
//img = new Image("\\myimage.png");
}catch(Exception e){
System.out.println("error while creating image");
e.printStackTrace();
}
try{
gui.setImgV(img);
}catch(Exception e){
System.out.println("error while setting up the image");
}
}
This is what prints out:
error while creating image
java.lang.IllegalArgumentException: Invalid URL: Invalid URL or resource not found
at javafx.scene.image.Image.validateUrl(Image.java:990)
at javafx.scene.image.Image.(Image.java:538)
On Windows platform, for an image placed inside src/jopofx :
img = new Image("\\jopofx\\myimage.png");
or
img = new Image("/jopofx/myimage.png");
Then you can create an ImageView using:
ImageView imageView = new ImageView(img);
Further, you can also directly initialize an ImageView without initializing an Image by:
ImageView imageView = new ImageView("/jopofx/myimage.png");
Also, make sure you are using the import javafx.scene.image.Image;
I found a working example from a blog short after I posted my question.
Hopefully this example will be helpful to someone:
InputStream stream = getClass().getResourceAsStream("images/"+imageName+".jpg");
//"images/" is the a local directory where all my images are located
Image newImage = new Image(stream);
imgV.setImage(newImage);
Related
Basically I have a method to load an Image from database into an imageView and a second method to change the image I'm sucessfully running both methods without getting an exception but after the setImage in changeImage() method what do I need to update and how (scene,stage) is it possible at all. I know that there is no method like repaint() in swing in javafx, so how do I approach this ?
public class MainMenuController implements Initializable {
/**
* Initializes the controller class.
*/
#Override
public void initialize(URL url, ResourceBundle rb) {
// TODO
}
private AnchorPane stck1;
#FXML
private AnchorPane openSecondWindow(ActionEvent event) throws Exception {
GUIController ctrl = new GUIController();
Stage stage = new Stage();
setStck1((AnchorPane) FXMLLoader.load(InteractiveFictionGame2.class.getResource("GUI.fxml")));
ImageView img_1 = new ImageView(ctrl.loadImg().getImage());
img_1.setPreserveRatio(true);
img_1.setSmooth(true);
img_1.setCache(true);
getStck1().getChildren().add(img_1);
Scene scene = new Scene(getStck1());
stage.setTitle("Interactive Fiction Game");
stage.setScene(scene);
stage.setFullScreen(true);
// stage.sizeToScene();
stage.show();
return getStck1();
}
public class GUIController implements Initializable {
#FXML
private TabPane tb1;
/**
* Initializes the controller class.
*
* #param url
*/
#Override
public void initialize(URL url, ResourceBundle rb) {
// TODO
}
#FXML
private ImageView img_1;
public ImageView loadImg() {
try {
con = DriverManager.getConnection(host, unm, pswrd);
stmnt = con.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_READ_ONLY);
rs = stmnt.executeQuery(SQL);
rs.next();
fis = rs.getBinaryStream(4);
imgt = javax.imageio.ImageIO.read(fis);
Image newImg = SwingFXUtils.toFXImage(imgt, null);
img_1 = new ImageView();
img_1.setImage(newImg);
rs.close();
stmnt.close();
con.close();
} catch (Exception e) {
System.out.println("Not working");
}
return img_1;
}
public void changeImage() {
..
fis = rs.getBinaryStream(1);
imgt = javax.imageio.ImageIO.read(fis);
Image newImg = SwingFXUtils.toFXImage(imgt, null);
img_1.setImage(newImg);
...
} catch (Exception e) {
System.out.println("Not working");
}
return img_1;
}
Your Issue
If you have a member node in your controller which you inject using #FXML, you should never create a new object instance using a new constructor and assign that new object to your existing reference. Instead just use the object which FXML created for you.
You have:
#FXML
private ImageView img_1;
That's fine.
Then in loadImg, you have:
img_1 = new ImageView();
img_1.setImage(newImg);
That is bad.
You already have an ImageView which the FXMLLoader created for you when you loaded your FXML document. The FXML Loader then assigned that ImageView to your img_1 reference because you used an #FXML annotation.
How to Fix it
So all you need to do is to stop creating new ImageViews and only write:
img_1.setImage(newImg);
And you are done.
Why it works
The Image property of ImageView is an observable property. The JavaFX system observes the Image property for any changes and if it changes, automatically updates the image displayed on the screen for the ImageView. You don't need to perform any repaint call (there is no such repaint routine to call in any case).
Background Reading
If you want to understand the JavaFX scene graph architecture better, read the Oracle tutorial on it:
Working with the JavaFX Scene Graph.
Some Tips
You can create a JavaFX image directly from an InputStream, you don't need to use ImageIO and SwingFXUtils for this task.
You can use a Task to communicate with a database and your application may be more responsive.
It is probably simpler to read the image from a file or over http rather than from a database.
Disclaimer
Besides the issue pointed out here, there may be other errors in code you have not provided which may prevent you from getting your application to work as you wish.
Java I graduate here:
In my JavaFX term project I had to update an imageView object upon a setOnAction Event (clicking a button). This allowed the program user to click through a series of pictures.
The following worked great:
First create your Image and ImageView instances:
Image imageObject = new Image();
ImageView imageViewObject = new ImageView();
Then down in the code a button event causes the (next) image to be assigned and updated as follows:
btn.setOnAction(e -> {
imageIndex++;
imageFilename = imageNamesArray.get(imageIndex);
imageObject = new Image(imageFilename);
imageViewObject.setImage(imageObject);
}
Note: The filename(s) in my project are jpg file (names) saved as String elements in an ArrayList(). The button click also increments the array index to the next jpg filename (and path or URL) and the new image would appear.
So as in the aforementioned answer you only create one ImageViewObject but you do reassign a new image to the image object "imageObject" each time.
I have built my application using scenebuilder for javafx. I have a form where a person has to upload an image. I used this code
public void photoChooser(ActionEvent evt) {
System.out.println("photoChooser method is called");
try{
FileChooser fileChooser= new FileChooser();
fileChooser.setTitle("Choose a file");
File file = fileChooser.showOpenDialog(stagehere);
if(file != null){
System.out.println(file);
String img = file.toString();
//Image image = new ImageIcon(img);
try{
// image= new Image();
Image image = new Image(img);
} catch (Exception e) {System.out.println("Can't upload image " + e);}
//employeeImage.setImage(image);
try{
// employeeImage.setImage(image);
} catch(Exception e){System.out.println("Can't set the image" + e);}
employeeImage.setFitWidth(150);
employeeImage.setFitHeight(150);
}
And I got this error
photoChooser method is called
A:\images\fb\status\asd.jpg
Can't upload image java.lang.IllegalArgumentException: Invalid URL: unknown protocol: a
The constructor of Image expects an URL and not a file path. Therefore if there is a ":" in the string, everything up to that point is interpreted as the protocol (normally something like http, file or ftp).
You have to change the line
String img = file.toString();
to
String img = file.toURI().toURL().toExternalForm();
This gets the URL from the file before converting to string. I converted to URI first since File.toURL is deprecated and that's the suggested "workaround".
I managed to create the functionality to upload an image with the "gwtuploaded" to the app engine and store the image as an blob. My problem now is: The url that I get from imagesService.getServingUrl(suo) links to an image which is smaller than the image i uploaded. If i check the image in the blob viewer in the app engine console, it seems to have the correct size.
Why do I get a resized version of my image with the following code. Can I somehow retrieve the url to the full sized image?
My code looks like this:
public class MyUploadAction extends AppEngineUploadAction{
#Override
public String executeAction(HttpServletRequest request, List<FileItem> sessionFiles) throws UploadActionException {
String imageUrls = "";
// Image service is needed to get url from blob
ImagesService imagesService = ImagesServiceFactory.getImagesService();
// Get a file service -> write the blob
FileService fileService = FileServiceFactory.getFileService();
// Iterate over the files and upload each one
for(FileItem myFile : sessionFiles){
InputStream imgStream = null;
// construct our entity objects
Blob imageBlob = null;
// Create a new Blob file with mime-type "image/png"
AppEngineFile file = null;
FileWriteChannel writeChannel = null;
try {
// get input stream from file
imgStream = myFile.getInputStream();
imageBlob = new Blob(IOUtils.toByteArray(imgStream));
// create empty app engine file with mime type of uploaded file e.g.: image/png, image/jpeg
file = fileService.createNewBlobFile(myFile.getContentType());
// Open a channel to write to it
boolean lock = true;
writeChannel = fileService.openWriteChannel(file, lock);
// This time we write to the channel directly
writeChannel.write(ByteBuffer.wrap(imageBlob.getBytes()));
} catch (IOException e) {
e.printStackTrace();
}finally{
// Now finalize
try {
writeChannel.closeFinally();
} catch (IllegalStateException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
// Get the url from the blob
ServingUrlOptions suo = ServingUrlOptions.Builder.withBlobKey(fileService.getBlobKey(file)).secureUrl(true);
imageUrls += imagesService.getServingUrl(suo);
imageUrls = imageUrls.replaceFirst("0.0.0.0", "127.0.0.1");
System.out.println(imageUrls);
}
return imageUrls ;
}
}
I tried and found that image service got a maximum image output of 1600x1600.
see here and search for 1600: https://developers.google.com/appengine/docs/java/images/
That applies even if you don't request for an resize.
To serve the image in original size, you shouldn't use the image service, just output directly from (e.g. blobstore)
I am trying to load my computer folder images into a wall of thumbnails. I read on a thread from another forum that ImageView "url" instance variable does not support system paths. I tried with the solution there, but it throws an exception: java.lang.OutOfMemoryError: Java heap space as it keeps reading the file.
another problem is it keeps giving me warning of using package javafx.ext -> SwingUtils.toFXImage method.
I have also tried to input the URL like that:
"file://localhost//Users/USER/Pictures/Camera/test/1.JPG"
I tried to display a number of images, but it always only displays 3 to 4 images.
I checked with the error function given from ImageView, it does not indicate that the reading of my images encountered an error.
Are there any alternatives?
Code
function load() {
println("RUNTIME {Runtime.getRuntime().maxMemory()}");
System.gc();
Runtime.getRuntime().freeMemory();
//MAC Folder PATH
var path: String = "/Users/username/Pictures/camera/test/1.JPG";;
var file: File = new File(path);
//http://download.oracle.com/docs/cd/E17802_01/javafx/javafx/1.3/docs/api/javafx.ext.swing/javafx.ext.swing.SwingUtils.html
//public toFXImage(image: java.awt.image.BufferedImage) : Image
//Creates a JavaFX Image from a BufferedImage.
img = SwingUtils.toFXImage(ImageIO.read(file));
}
It is not clear exactly what you are trying to do. If you are talking about JavaFX 2.0, the following code works. If you are loading a lot of images and need to conserve memory, you only have to create enough ImageView's for the number you want to display at one time. Then as you page through the images, you can swap out the Image object contained in the ImageView.
public void start(Stage primaryStage) {
primaryStage.setTitle("Hello World");
StackPane root = new StackPane();
Scene scene = new Scene(root, 300, 250);
File file = new File("/System/Library/CoreServices/loginwindow.app/Contents/Resources/LogOut.png");
Image image = new Image(file.toURI().toString());
ImageView iv = new ImageView(image);
root.getChildren().add(iv);
primaryStage.setScene(scene);
primaryStage.show();
}
its simple: open a image with a browser and copy the whole url of the pic and paste it as a parameter of the Image object. DO NOT REMOVE "file///:" because this makes the image loadable. you will get your other logic from there. happy coding e.g
Image image = new Image("file:///C:/Users/Nigel/Desktop/my_image.png");
ImageView imgview = new ImageView(image);
None of the previous answers worked for me. However, this one, which I saw a while back but can't find an original link from, works flawlessly.
#Override
public void start(Stage primaryStage) throws Exception {
//create a pane to hold the image views
Pane pane = new HBox(10);
pane.setPadding(new Insets(5,5,5,5));
//create the image to be used!
Image image = new Image("/Content/vortex.jpg");
//set some custom properties and add an image
ImageView imageView = new ImageView(image);
imageView.setFitHeight(100);
imageView.setFitWidth(100);
pane.getChildren().add(imageView);
//add the second image view with this image and no custom properties
pane.getChildren().add(new ImageView(image));
ImageView imageView2 = new ImageView(image);
imageView2.setRotate(45);
pane.getChildren().add(imageView2);
Scene scene = new Scene(pane, 200, 200);
primaryStage.setScene(scene);
primaryStage.show();
}
public static void main(String[] args) {
Application.launch(args);
}
The key is that when you create the image, START the path with a '/' (ie: "/Content/vortex.jpg"). Note that in this setup, the root folder is the src folder in most IDEs.
sorry if my answer came a little bit late but that was my approach and it works 100% wherever you are putting your file
1.assign your image to File
2.parse the File to URI
3.assign the uri.toString() to the image
ex code:
File imageFile = new File("path/to/image/outside/your/jar/awesomeless.jpg");
String fileLocation = imageFile.toURI().toString();
Image fxImage = new Image(fileLocation);
or you can simply put it all together like this:
Image fxImage = new Image(new File("path/.../awesomemore.jpg").toURI().toString());
and please if anyone knows a better approach let us know!
Another solution is to pass the InputStream into the Image class constructor; and is working...
public void start(Stage primaryStage) {
primaryStage.setTitle("Hello World");
StackPane root = new StackPane();
Scene scene = new Scene(root, 300, 250);
java.io.FileInputStream fis = new FileInputStream("/System/Library/CoreServices/loginwindow.app/Contents/Resources/LogOut.png");
ImageView iv = new ImageView(new Image(fis));
root.getChildren().add(iv);
primaryStage.setScene(scene);
primaryStage.show();
}
I'm using netbeans IDE to practice some Java basic code. But I'm unsuccessful to draw a PNG image. Below is my code,
package JavaApplication1;
import javax.swing.*;
import java.awt.*;
class MyCanvas extends JComponent
{
Image img;
public MyCanvas(){
img = Toolkit.getDefaultToolkit().createImage("pengbrew.png");
}
public void paintComponent(Graphics g){
super.paintComponent(g);
g.drawImage(img, 0, 0, null);
}
}
public class JavaGame
{
public static void main(String args[]){
JFrame window = new JFrame("Image demo");
window.getContentPane().add( new MyCanvas() );
window.setSize(400,400);
window.setVisible(true);
}
}
I added the images in the netbeans project.
Please advise.
Many thanks.
easiest ways is look for JLabel that's best of JComponents for Icon/ImageIcon examples here
To load an image use ImageIO.read(File file). It's a newer API, easier to use and better supported. A tutorial on loading images is here http://docs.oracle.com/javase/tutorial/2d/images/loadimage.html if you need some more pointers.
Your code would look like this instead,
Image img;
public MyCanvas(){
try {
img = ImageIO.read(new File("pengbrew.png"));
} catch (IOException e) {
// Handle exception if there is one.
}
}
For the long answer about why the method you were using wasn't working is probably because of the following...
Your image may be in the proper location and instead Toolkit.createImage() hasn't finished loading the image before the frame comes up to paint. Toolkit.createImage() returns control back to your application before the underlying image has actually finished being loaded. You can usually verify if this is the issue by resizing your application to force it to repaint. If after a few seconds of trying to resize the application the image shows up it was due to the image not being loaded during the first paint calls.
To ensure that the image is loaded before you continue you need to use a MediaTracker. Here is some example code to ensure loading of Image is complete before using it.
Component component = new Component() {};
MediaTracker TRACKER = new MediaTracker(component);
...
Image image = Toolkit.getDefaultToolkit().createImage("imageToLoad.png");
synchronized(TRACKER) {
int id = ++mediaTrackerID;
TRACKER.addImage(image, id);
try {
TRACKER.waitForID(id, 0);
} catch (InterruptedException ex) {
image = null;
}
TRACKER.removeImage(image, id);
}
// Now you can use your image.
You'll see code just like this in the ImageIcon class in the method loadImage(Image image).