Uploading and displaing an image using JavaFX - java

I'm working with JavaFX, where I have written a code that contains display Image, through I want to display the image on my scene, but it's not working. The image doesn't display.
When I'm using the getAbsolutePath() it also displays an error. Although 70% of my coding is done, I'm just stuck with displaying images on the scene (without uploading it).
Here is the code I'm working with:
package application;
import java.util.HashMap;
import java.io.File;
import javafx.application.Application;
import javafx.stage.Stage;
import javafx.stage.FileChooser;
import javafx.scene.Scene;
import javafx.scene.text.*;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.StackPane;
import javafx.scene.layout.HBox;
import javafx.scene.layout.VBox;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.shape.Circle;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
public class Main extends Application {
public ImageView iv;
private GridPane gridpane;
//Image
Image img = new Image("application/PA_Image.jpg");
#Override
public void start(Stage primaryStage) {
try {
//Upload Image Button
final Button button = new Button("Display Image");
//FileChooser
final FileChooser fileChooser = new FileChooser();
button.setOnAction(e -> {
File selectedFile = fileChooser.showOpenDialog(primaryStage);
if (selectedFile != null) {
System.out.println(selectedFile.getAbsolutePath());
Image image = new Image(selectedFile.getAbsolutePath());
iv = new ImageView(image);
//Image uploadedImage = new Image(selectedFile.getAbsolutePath());
}
});
final StackPane stac = new StackPane();
stac.getChildren().add(button);
Scene scene = new Scene(stac,400,400);
scene.getStylesheets().add(getClass().getResource("application.css").toExternalForm());
primaryStage.setScene(scene);
primaryStage.show();
} catch(Exception e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
launch(args);
}
}
So, what I need, is to display images on my scene by clicking the button and selecting an image.

The Image() constructor expects a URI and not an Absolute path.
There are two ways to approach this.
Turn your absolutePath in a URI by adding the required prefix file://
Use InputStream which holds the Image data and you don't have to care about the Path after it has been created. I like this way better.
Example:
button.setOnAction(e -> {
File selectedFile = fileChooser.showOpenDialog(primaryStage);
if (selectedFile != null) {
System.out.println(selectedFile.getAbsolutePath());
final InputStream targetStream; // Creating the InputStream
try
{
targetStream = new DataInputStream(new FileInputStream(selectedFile));
Image image = new Image(targetStream);
iv = new ImageView(image);
} catch (FileNotFoundException fileNotFoundException)
{
fileNotFoundException.printStackTrace();
}
}
});
There are also some other problems with your code.
Create your ImageView and initialize it. Not when the button is clicked but right at the beginning
Add the ImageView to your Scene
Do not create new ImageView every time the button is clicked, just change the Image.
This is my code based on yours:
public ImageView iv = new ImageView();
private GridPane gridpane;
#Override
public void start(Stage primaryStage) {
try {
//Upload Image Button
final Button button = new Button("Display Image");
//FileChooser
final FileChooser fileChooser = new FileChooser();
button.setOnAction(e -> {
File selectedFile = fileChooser.showOpenDialog(primaryStage);
if (selectedFile != null) {
final InputStream targetStream;
try {
targetStream = new DataInputStream(new FileInputStream(selectedFile));
Image image = new Image(targetStream);
iv.setImage(image); // Set Image
} catch (FileNotFoundException fileNotFoundException) {
fileNotFoundException.printStackTrace();
}
}
});
final StackPane stac = new StackPane();
stac.getChildren().add(button);
stac.getChildren().add(iv); // Add ImageView
Scene scene = new Scene(stac, 1600, 800);
//scene.getStylesheets().add(getClass().getResource("application.css").toExternalForm());
primaryStage.setScene(scene);
primaryStage.show();
} catch (Exception e) {
e.printStackTrace();
}
}

Related

Error: Unable to initialize main class FileChooser_1 Caused by: java.lang.NoClassDefFoundError: Stage [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 12 months ago.
Improve this question
Here I have written the following code. I can't run the program, and the error mentioned below keeps appearing. I tried many probable solutions but in vain.
import java.beans.EventHandler;
import java.io.File;
import javafx.application.Application;
import javafx.collections.*;
import javafx.event.ActionEvent;
import javafx.geometry.*;
import javafx.scene.Scene;
import javafx.scene.canvas.*;
import javafx.scene.control.*;
import javafx.scene.layout.*;
import javafx.scene.paint.*;
import javafx.scene.shape.*;
import javafx.scene.text.*;
import javafx.stage.FileChooser;
import javafx.stage.Stage;
public class FileChooser_1 extends Application {
// launch the application
public void start(Stage stage) {
try {
// title
stage.setTitle("Filechooser");
//File chooser create
FileChooser file_chooser = new FileChooser();
// define Label
Label lab = new Label("select file");
// Button new
Button b = new Button("open dialog");
// create Event Handler
EventHandler<ActionEvent> eve
= new EventHandler<ActionEvent>() {
public void handle(ActionEvent e) {
// get file
File file = file_chooser.showOpenDialog(stage);
if (file != null) {
lab.setText(file.getAbsolutePath()
+ " selected");
}
}
};
b.setOnAction(event);
// create Button
Button b1 = new Button("save");
// Event Handler
EventHandler<ActionEvent> eve1
= new EventHandler<ActionEvent>() {
public void handle(ActionEvent e) {
// get file
File file = file_chooser.showSaveDialog(stage);
if (file != null) {
lab.setText(file.getAbsolutePath()
+ " selected");
}
}
};
b1.setOnAction(eve1);
// VBox
VBox vbox = new VBox(30, label, button, button1);
// set Alignment
vbox.setAlignment(Pos.CENTER);
// create scene
Scene scene = new Scene(vbox, 800, 500);
// scene
stage.setScene(scene);
stage.show();
} catch (Exception e) {
System.out.println(e.getMessage());
}
}
// Main Method
public static void main(String args[]) {
launch(args);
}
}
I am getting the following error:
Error: Unable to initialize main class FileChooser_1
Caused by: java.lang.NoClassDefFoundError: Stage
It will be really nice if you can help me with this.
With some attention to detail, your code works. In particular, especially when just starting out,
Use Java naming conventions.
Use meaningful names; for example, instead of Button b, try Button openButton.
When using detailed comments, keep them up to date; note how meaningful names make some comments superfluous.
Use constants for consistency.
As #jewelsea notes, your program imports java.beans.EventHandler; it should import javafx.event.EventHandler.
As #jewelsea notes, "Only import classes you use."
Let the layout do the work.
I can't explain the error in your question; I see errors related to the incorrect import for EventHandler. If you're using an IDE, it may be reporting errors from a different compilation unit. When in doubt, do a clean build, move the code to a new file, or move to a different development environment, e.g. the command line. As a concrete example, this simple VersionCheck illustrates both a minimal ant script, invoked as ant run, and a simple shell script, invoked as .run.sh:
#!/bin/sh
JFX="--module-path /Users/Shared/javafx-sdk-17.0.1/lib --add-modules ALL-MODULE-PATH"
javac $JFX *.java && java $JFX VersionCheck
import javafx.event.EventHandler;
import java.io.File;
import javafx.application.Application;
import javafx.event.ActionEvent;
import javafx.geometry.*;
import javafx.scene.Scene;
import javafx.scene.control.*;
import javafx.scene.layout.*;
import javafx.stage.FileChooser;
import javafx.stage.Stage;
public class FileChooser1 extends Application {
private static final int PADDING = 32;
#Override
public void start(Stage stage) {
// title
stage.setTitle("FileChooser");
//File chooser create
FileChooser fileChooser = new FileChooser();
// define Label
Label label = new Label("Select a file to open or save:");
// open Button
Button openButton = new Button("Open");
// open Event Handler
EventHandler<ActionEvent> openHandler = new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent e) {
// get file name
File file = fileChooser.showOpenDialog(stage);
if (file != null) {
label.setText(file.getName() + " selected");
}
}
};
openButton.setOnAction(openHandler);
// create save button
Button saveButton = new Button("Save");
// save Event Handler
EventHandler<ActionEvent> saveHandler = new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent e) {
// save file
File file = fileChooser.showSaveDialog(stage);
if (file != null) {
label.setText(file.getName() + " selected");
}
}
};
saveButton.setOnAction(saveHandler);
// VBox
VBox vBox = new VBox(PADDING, label, openButton, saveButton);
// set Alignment
vBox.setAlignment(Pos.CENTER);
vBox.setPadding(new Insets(PADDING));
// create scene
Scene scene = new Scene(vBox);
// scene
stage.setScene(scene);
stage.show();
}
public static void main(String args[]) {
launch(args);
}
}

Cannot refresh scene/Nodes in JavaFX when update

I'm new to JavaFX. I try to program a simple GUI but I face those problem whom might be related.
I set files with a File Chooser and want to do pretty basic operations:
save the last folder used
write the name of the selected file in the VBox
Here's my code (which compiles):
import java.io.File;
import java.io.IOException;
import javafx.application.Application;
import javafx.geometry.Insets;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.Pane;
import javafx.scene.layout.VBox;
import javafx.stage.FileChooser;
import javafx.stage.Stage;
import javafx.stage.StageStyle;
public class Main extends Application {
public static Stage primaryStageS;
public static Scene mainScene;
public void start(Stage primaryStage) throws Exception {
primaryStage.setScene((new Test(primaryStage).getScene()));
primaryStageS = primaryStage;
primaryStage.setTitle("Parcel Manager Main Page");
primaryStage.initStyle(StageStyle.DECORATED);
VBox main = new VBox(new Label("Test program"));
mainScene = new Scene(main, 800, 600);
primaryStage.setScene((new Test(primaryStage)).getScene());
primaryStage.show();
}
public static void main(String[] args) {
Application.launch(args);
}
public class Object1 {
String name;
public Object1(File f) throws IOException {
name = f.getName();
}
public String getName() {
return name;
}
}
public class Test {
Object1 collec;
String collecName;
File lastFolder;
Pane rootGroup;
public Test(Stage stage) {
setButtons(stage);
}
public void setButtons(Stage stageGoal) {
VBox vbox = new VBox();
Button b = getButton(stageGoal);
vbox.getChildren().addAll(b, new Label(getCollecName() == null ? "no name" : collecName));
final GridPane inputGridPane = new GridPane();
GridPane.setConstraints(vbox, 0, 0);
inputGridPane.getChildren().addAll(vbox);
rootGroup = new VBox(12);
rootGroup.getChildren().addAll(inputGridPane);
rootGroup.setPadding(new Insets(12, 12, 12, 12));
}
public Button getButton(Stage stage) {
FileChooser fileChooserParcel = new FileChooser();
fileChooserParcel.setInitialDirectory(getLastFolder());
Button button = new Button("Select a File");
button.setOnAction(e -> {
File f = fileChooserParcel.showOpenDialog(stage);
if (f != null) {
try {
collec = new Object1(f);
} catch (IOException e1) {
e1.printStackTrace();
}
setLastFolder(f.getParentFile());
setCollecName(collec);
setButtons(stage); // tried to reload every buttons - doesn't work
stage.setWidth(stage.getWidth() + 0.0001); // found this dirty hack but doesn't work
}
});
return button;
}
public void setCollecName(Object1 o1) {
collecName = o1.getName();
}
public String getCollecName() {
return collecName;
}
public File getLastFolder() {
return lastFolder;
}
public void setLastFolder(File folder) {
System.out.println("set last folder: " + folder);
lastFolder = folder;
}
private Scene getScene() {
return new Scene(rootGroup, 800, 600);
}
}
}
I cannot refresh the Nodes, either to set a current Initial Directory or display the collecName on the VBox. I tried to regenerate them with reloading of objects or resizing the window, but nothing works. When I print the variables on console, I see that they changes. But haven't found any refresh method for any of my objects.
I bet it's a design program issue, but I have been moving things around for the last week and doesn't know how to fix this.
Thanks !
You are only setting the initial directory once. I guess you want to set it every time you click the button. So move that line of code to inside the handler.
Compare the below getButton() method with yours.
public Button getButton(Stage stage) {
FileChooser fileChooserParcel = new FileChooser();
Button button = new Button("Select a File");
button.setOnAction(e -> {
fileChooserParcel.setInitialDirectory(getLastFolder()); // CHANGE HERE.
File f = fileChooserParcel.showOpenDialog(stage);
if (f != null) {
try {
collec = new Object1(f);
} catch (IOException e1) {
e1.printStackTrace();
}
setLastFolder(f.getParentFile());
setCollecName(collec);
setButtons(stage); // tried to reload every buttons - doesn't work
stage.setWidth(stage.getWidth() + 0.0001); // found this dirty hack but doesn't work
}
});
return button;
}

java - images in javafx

I am still pretty new to java and i am still learning. I have never used images before so it is possible if I can have help add a image. I am not that sure what needs to be done in order to add one. Thank you
enter image description here
here is the code:
import javafx.application.Application;
import javafx.beans.binding.StringBinding;
import javafx.beans.property.BooleanProperty;
import javafx.beans.property.ReadOnlyObjectProperty;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.ChoiceBox;
import javafx.scene.control.RadioButton;
import javafx.scene.control.TextArea;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.HBox;
import javafx.scene.layout.Pane;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;
class User {
private StringProperty order = new SimpleStringProperty();
public String getOrder() {
return order.get();
}
public void setOrder(String order) {
this.order.set(order);
}
public StringProperty orderProperty() {
return order;
}
}
public class pizza extends Application {
private User user = new User();
#Override
public void start(Stage stage) throws Exception {
stage.setTitle("Pizza System");
Button btn = new Button();
btn.setText("place order");
BorderPane pane = new BorderPane();
pane.setBottom(btn);
btn.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent event) {
btn.setText("Order has been placed. Please wait at least 30 minutes.");
}
});
RadioButton tomatoButton = new RadioButton("Tomato");
RadioButton pepperButton = new RadioButton("Pepper");
RadioButton mushroomButton = new RadioButton("Mushrooms");
ChoiceBox<String> pizzaType = new ChoiceBox<String>();
pizzaType.getItems().addAll("", "Small", "Medium", "Large");
pizzaType.getSelectionModel().selectFirst();
HBox topHBox = new HBox(15.0, tomatoButton, pepperButton, mushroomButton, pizzaType);
// create custom Binding that binds selection of radio buttons and choice box
StringBinding orderBinding = createOrderBinding(tomatoButton.selectedProperty(), pepperButton.selectedProperty(), mushroomButton.selectedProperty(), pizzaType.getSelectionModel().selectedItemProperty());
// bind orderBinding to orderProperty of User
user.orderProperty().bind(orderBinding);
TextArea orderArea = new TextArea();
// bind orderProperty of User to textProperty of TextArea
orderArea.textProperty().bindBidirectional(user.orderProperty());
BorderPane root = new BorderPane();
root.setTop(topHBox);
root.setCenter(orderArea);
root.setBottom(btn);
Scene scene = new Scene(root, 400, 300);
stage.setScene(scene);
stage.show();
}
public StringBinding createOrderBinding(BooleanProperty tomato, BooleanProperty pepper, BooleanProperty mushroom, ReadOnlyObjectProperty<String> selectedPizzaType) {
StringBinding binding = new StringBinding() {
{
// bind 4 provided properties.
super.bind(tomato, pepper, mushroom, selectedPizzaType);
}
#Override
protected String computeValue() {
StringBuilder sb = new StringBuilder("Pizza content:\n");
if (tomato.get())
sb.append("\tTomato\n");
if (pepper.get())
sb.append("\tPepper\n");
if (mushroom.get())
sb.append("\tMushroom\n");
sb.append("Pizza type:\n").append("\t" + selectedPizzaType.get());
return sb.toString();
}
};
return binding;
}
public static void main(String[] args) {
Application.launch(args);
}
}
JavaFX uses an Image to load the image file and it has a node called ImageView to place that image on the screen graph.
Considering that the image is present at the same location as your class file, you can use this:
// Load Image
Image image = new Image(getClass().getResource("image.jpg").toExternalForm());
// Set the Image on the ImageView
ImageView imageView = new ImageView(image);
// specify a size
imageView.setFitWidth(200);
imageView.setFitHeight(200);
// Place ImageView in a container
root.setRight(imageView);

Complete JFXPanel to image

I want to take a snapshot of a website without any video, so it's just plain text with some css and pictures.
I am using a WebView (which is the scene of the JFXPanel) to load the website and then save it via
WritableImage image = scene.snapshot(new WritableImage(1920, 1080));
BufferedImage bufferedImage = SwingFXUtils.fromFXImage(image, null);
ImageIO.write(bufferedImage, "png", file);
(where "scene" is the scene of the JFXPanel)
but the saved image just displays a part of the website, instead of the complete content (see picture).
How do I ensure/enforce that the dimensions of the image matches the dimensions of the JFXPanel content and everthing is visible?
Complete Code:
package renderer;
import javafx.application.Application;
import javafx.application.Platform;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.concurrent.Worker;
import javafx.embed.swing.JFXPanel;
import javafx.embed.swing.SwingFXUtils;
import javafx.scene.Scene;
import javafx.scene.image.WritableImage;
import javafx.scene.web.WebView;
import javafx.stage.Stage;
import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.List;
public class HtmlRenderer extends Application {
private JFXPanel jfxPanel;
private WebView webView;
public void start(Stage stage) {
jfxPanel = new JFXPanel();
webView = new WebView();
webView.getEngine().getLoadWorker().stateProperty().addListener(
new ChangeListener<Worker.State>() {
#Override
public void changed(ObservableValue ov, Worker.State oldState, Worker.State newState) {
if (newState == Worker.State.SUCCEEDED) {
HtmlRenderer.this.toImage(jfxPanel.getScene());
try {
Platform.exit();
HtmlRenderer.this.stop();
} catch (Exception e) {
e.printStackTrace();
}
}
}
});
jfxPanel.setScene(new Scene(webView));
this.updateView("http://www.stackoverflow.com/");
}
private void toImage(Scene scene) {
WritableImage image = scene.snapshot(new WritableImage(1920, 1080));
// TODO: save in matching dir using proper filename
File file = new File("D:/workspace/SiteChecker/test.png");
try {
BufferedImage bufferedImage = SwingFXUtils.fromFXImage(image, null);
ImageIO.write(bufferedImage, "png", file);
} catch (IOException e) {
// TODO: exception handling
}
}
public void updateView(String url) {
webView.getEngine().load(url);
}
private void reloadView() {
webView.getEngine().reload();
}
}
So I found a solution, but it's far from perfect and not really perfomant.
However, nothing else works for me.
The trick is to load the website once, determine width and height of the site. The second time I set the preferred size of the Webview to the determined values and load the website again with the new size. I think it's because the first time only the visible part is rendered.
The width and height can be determined with javascript, e.g.:
private int getPageWidth(WebView webView) {
String script = "Math.max(" +
"document.body.scrollWidth, document.body.offsetWidth," +
"document.documentElement.clientWidth, document.documentElement.scrollWidth," +
"document.documentElement.offsetWidth );";
WebEngine engine = webView.getEngine();
int maxWidth = (int) engine.executeScript(script);
return maxWidth;
}
For some reason some websites have a funny end/bottom i.e. there is a lot of empty space.

Java change Label image

I have two different StackPanes with HBoxes I want to change the image of a label in the second StackPane with a Label(MouseListener) in the first StackPane I think the problem is that the Label doesn't gets repainted or reloaded
First StackPane:
Label label= new Label("",new ImageView(ClearSpace));
label.addEventHandler(MouseEvent.MOUSE_CLICKED, (MouseEvent event) -> {
HotBar hb = new HotBar();
if(hb.getX1() == 0){
hb.setImageX1(5);
}
event.consume();
});
Second StackPane(HotBar):
public Label x1;
Image image= new Image(getClass().getResourceAsStream("/resources/images/Test.png"));
...
Label x1 = new Label("",new ImageView(image));
...
public void setImage(int i){
if(i == 5){
x1.setGraphic(new ImageView(image2));
}
}
I think these are the importantst parts of hte code
setImage() is definetly working if you use it below Label x1 = ... it works
In your EventHandler you create a new instance of HotBar on which you do changes, but this instance is not linked to the scene.
Instead you should pass the instance of HotBar into the other class and use that in your event handler.
package helloworld;
import javafx.application.Application;
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.Pane;
import javafx.stage.Stage;
/**
* Created by matt on 3/22/16.
*/
public class SwapLabel extends Application {
int i = 0;
public static void main(String[] args) {
launch(args);
}
#Override
public void start(Stage primaryStage) throws Exception {
Pane root = new Pane();
Image img1 = new Image("http://www.logotemplater.com/freelogostemplates/voope-free-logo-template.png", true);
Image img2 = new Image("http://www.logotemplater.com/freelogostemplates/zoozz-vector-logo-template-sample.png", true);
Label l = new Label("", new ImageView(img1));
l.addEventHandler(MouseEvent.MOUSE_CLICKED, e->{
i = (i+1)%2;
if(i==0){
l.setGraphic(new ImageView(img1));
}else{
l.setGraphic(new ImageView(img2));
}
});
root.getChildren().add(l);
primaryStage.setScene(new Scene(root, 200, 200));
primaryStage.show();
}
}
This appears to be what you are trying to do, but this works. So most likely something else is happening.

Categories