I am attempting to display an image file as soon as it is selected from a file chooser. The file chooser is restricted to .png and .jpg files with the selected files being stored in a variable of type File. To do this I have set up an ImageView, and I wish to set the image with this new file only problem is it is of type File not Image.
How can this be achieved? Code so far...
public void fileSelection(){
FileChooser fileChooser = new FileChooser();
fileChooser.setTitle("Select Profile Picture");
fileChooser.getExtensionFilters().addAll(new FileChooser.ExtensionFilter("Image Files", "*.png", "*jpg"));
File selectedFile = fileChooser.showOpenDialog(null);
File selectedFileInput = selectedFile;
if(selectedFile != null) {
selectedFileOutput.setText("File selected: " + selectedFile.getName());
previewPicture.setImage();
} else {
selectedFileOutput.setText("Please select a profile picture...");
}
}
You can simply create an image with
Image image = new Image(selectedFile.toURI().toString());
and then place it in the ImageView:
previewPicture.setImage(image);
Other constructors offer more control over resources required for loading the image. If you want to force the image to be a certain size, you can resize it on loading, which will save memory if the user chooses a large image but you only want to display a scaled-down version. Additionally, loading a large image may take time, so you should not load it on the UI thread. The Image constructors taking string versions of URLs have options to automatically load the image in a background thread. The following forces the width and height to be both no more than 240 pixels (while maintaining the original aspect ratio), and loads the image in the background (thus not blocking the UI):
Image image = new Image(selectedFile.toURI().toString(),
240, // requested width
240, // requested height
true, // preserve ratio
true, // smooth rescaling
true // load in background
);
See the documentation for other available constructors.
You create image and set to the ImageView as follows
Image image = new Image(new FileInputStream(selectedFile));
previewPicture.setImage(image);
I adding a late answer to demonstrate different image-file loading alternatives:
import java.io.File;
import java.net.URL;
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.layout.Pane;
import javafx.scene.layout.TilePane;
import javafx.stage.Stage;
public class ImagesFromFile extends Application {
#Override
public void start(Stage primaryStage) throws Exception{
primaryStage.setTitle("Load Images From File");
primaryStage.setScene(new Scene(new ImagePanel().getPane()));
primaryStage.show();
}
public static void main(final String[] args) {
launch(args);
}
}
/**
<pre>
Folders structure:
-Project
| - src
| | - package
| | | - ImagePanel.java
| | | - red_dot.png
| |
| | - resources
| | - blue_dot.png
|
| - black_dot.png
</pre>
*/
class ImagePanel{
private Pane pane;
ImagePanel() {
try{
//not embedded resource. doesn't work when packaged in jar
File file = new File("black_dot.png");
Image imageFromProjectFolder = new Image(file.toURI().toString());//or new Image(new FileInputStream("black_dot.png"));
ImageView view1 = new ImageView(imageFromProjectFolder);
URL url = getClass().getResource("red_dot.png");
Image imageFromSourceFolder = new Image(url.openStream());
ImageView view2 = new ImageView(imageFromSourceFolder); //or new ImageView("/package/red_dot.png");
url = getClass().getResource("/resources/blue_dot.png");
Image imageFromReourceFolder = new Image(url.openStream());
ImageView view3 = new ImageView(imageFromReourceFolder); //or new ImageView("/resources/blue_dot.png");
pane = new TilePane(view1, view2, view3);
} catch (Exception ex) {ex.printStackTrace();}
}
Pane getPane(){
return pane;
}
}
Related
I am attempting to display an image file as soon as it is selected from a file chooser. The file chooser is restricted to .png and .jpg files with the selected files being stored in a variable of type File. To do this I have set up an ImageView, and I wish to set the image with this new file only problem is it is of type File not Image.
How can this be achieved? Code so far...
public void fileSelection(){
FileChooser fileChooser = new FileChooser();
fileChooser.setTitle("Select Profile Picture");
fileChooser.getExtensionFilters().addAll(new FileChooser.ExtensionFilter("Image Files", "*.png", "*jpg"));
File selectedFile = fileChooser.showOpenDialog(null);
File selectedFileInput = selectedFile;
if(selectedFile != null) {
selectedFileOutput.setText("File selected: " + selectedFile.getName());
previewPicture.setImage();
} else {
selectedFileOutput.setText("Please select a profile picture...");
}
}
You can simply create an image with
Image image = new Image(selectedFile.toURI().toString());
and then place it in the ImageView:
previewPicture.setImage(image);
Other constructors offer more control over resources required for loading the image. If you want to force the image to be a certain size, you can resize it on loading, which will save memory if the user chooses a large image but you only want to display a scaled-down version. Additionally, loading a large image may take time, so you should not load it on the UI thread. The Image constructors taking string versions of URLs have options to automatically load the image in a background thread. The following forces the width and height to be both no more than 240 pixels (while maintaining the original aspect ratio), and loads the image in the background (thus not blocking the UI):
Image image = new Image(selectedFile.toURI().toString(),
240, // requested width
240, // requested height
true, // preserve ratio
true, // smooth rescaling
true // load in background
);
See the documentation for other available constructors.
You create image and set to the ImageView as follows
Image image = new Image(new FileInputStream(selectedFile));
previewPicture.setImage(image);
I adding a late answer to demonstrate different image-file loading alternatives:
import java.io.File;
import java.net.URL;
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.layout.Pane;
import javafx.scene.layout.TilePane;
import javafx.stage.Stage;
public class ImagesFromFile extends Application {
#Override
public void start(Stage primaryStage) throws Exception{
primaryStage.setTitle("Load Images From File");
primaryStage.setScene(new Scene(new ImagePanel().getPane()));
primaryStage.show();
}
public static void main(final String[] args) {
launch(args);
}
}
/**
<pre>
Folders structure:
-Project
| - src
| | - package
| | | - ImagePanel.java
| | | - red_dot.png
| |
| | - resources
| | - blue_dot.png
|
| - black_dot.png
</pre>
*/
class ImagePanel{
private Pane pane;
ImagePanel() {
try{
//not embedded resource. doesn't work when packaged in jar
File file = new File("black_dot.png");
Image imageFromProjectFolder = new Image(file.toURI().toString());//or new Image(new FileInputStream("black_dot.png"));
ImageView view1 = new ImageView(imageFromProjectFolder);
URL url = getClass().getResource("red_dot.png");
Image imageFromSourceFolder = new Image(url.openStream());
ImageView view2 = new ImageView(imageFromSourceFolder); //or new ImageView("/package/red_dot.png");
url = getClass().getResource("/resources/blue_dot.png");
Image imageFromReourceFolder = new Image(url.openStream());
ImageView view3 = new ImageView(imageFromReourceFolder); //or new ImageView("/resources/blue_dot.png");
pane = new TilePane(view1, view2, view3);
} catch (Exception ex) {ex.printStackTrace();}
}
Pane getPane(){
return pane;
}
}
I am having a error for my GUI. Trying to set title bar icon then be included in a Runnable JAR.
BufferedImage image = null;
try {
image = ImageIO.read(getClass().getClassLoader().getResource("resources/icon.gif"));
}
catch (IOException e) {
e.printStackTrace();
}
frame.setIconImage(image);
Here is the error I am getting:
Exception in thread "main" java.lang.IllegalArgumentException: input == null!
at javax.imageio.ImageIO.read(Unknown Source)
at GUI.<init>(GUI.java:39)
at GUI.main(GUI.java:351)
The image is in the correct directory which "resources" folder is the root of the
project file
First of all, change this line :
image = ImageIO.read(getClass().getClassLoader().getResource("resources/icon.gif"));
to this :
image = ImageIO.read(getClass().getResource("/resources/icon.gif"));
More info, on as to where lies the difference between the two approaches, can be found on this thread - Different ways of loading a Resource
For Eclipse:
How to add Images to your Resource Folder in the Project
For NetBeans:
Handling Images in a Java GUI Application
How to add Images to the Project
For IntelliJ IDEA:
Right-Click the src Folder of the Project. Select New -> Package
Under New Package Dialog, type name of the package, say resources. Click OK
Right Click resources package. Select New -> Package
Under New Package Dialog, type name of the package, say images. Click OK
Now select the image that you want to add to the project, copy it. Right click resources.images package, inside the IDE, and select Paste
Use the last link to check how to access this file now in Java code. Though for this example, one would be using
getClass().getResource("/resources/images/myImage.imageExtension");
Press Shift + F10, to make and run the project. The resources and images folders, will be created automatically inside the out folder.
If you are doing it manually :
How to add Images to your Project
How to Use Icons
A Little extra clarification, as given in this answer's first
code example.
QUICK REFERENCE CODE EXAMPLE(though for more detail consider, A little extra clarification link):
package swingtest;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.*;
/**
* Created with IntelliJ IDEA.
* User: Gagandeep Bali
* Date: 7/1/14
* Time: 9:44 AM
* To change this template use File | Settings | File Templates.
*/
public class ImageExample {
private MyPanel contentPane;
private void displayGUI() {
JFrame frame = new JFrame("Image Example");
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
contentPane = new MyPanel();
frame.setContentPane(contentPane);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
private class MyPanel extends JPanel {
private BufferedImage image;
public MyPanel() {
try {
image = ImageIO.read(MyPanel.class.getResource("/resources/images/planetbackground.jpg"));
} catch (IOException ioe) {
ioe.printStackTrace();
}
}
#Override
public Dimension getPreferredSize() {
return image == null ? new Dimension(400, 300): new Dimension(image.getWidth(), image.getHeight());
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawImage(image, 0, 0, this);
}
}
public static void main(String[] args) {
Runnable runnable = new Runnable() {
#Override
public void run() {
new ImageExample().displayGUI();
}
};
EventQueue.invokeLater(runnable);
}
}
There's a much easier way to load and set an image as a frame icon:
frame.setIconImage(
new ImageIcon(getClass().getResource("/resources/icon.gif")).getImage());
And thats all :)! You don't even have to use a try-catch block because ImageIcon does not throw any declared exceptions. And due to getClass().getResource(), it works both from file system and from a jar depending how you run your application.
If you need to check whether the image is available, you can check if the URL returned by getResource() is null:
URL url = getClass().getResource("/resources/icon.gif");
if (url == null)
System.out.println( "Could not find image!" );
else
frame.setIconImage(new ImageIcon(url).getImage());
The image files must be in the directory resources/ in your JAR, as shown in How to Use Icons and this example for the directory named images/.
I am creating image gallery using javafx. I found many things on internet regarding this but not able to get any suitable help for this issue. I have to create one image gallery like picasa viewer. all the images is in thumbnail view in my image view and after that when I select image that is in pop-up viewer. I did it some code for that but I didn't get proper output. All the images from the folder redraw from the same co-ordinates.
Below is my code and output.
#Override
public void initialize(URL url, ResourceBundle rb) {
String path = "/home/ubuntu/eclipse with liferay/Desktop/imagetest/";
File folder = new File(path);
File[] listOfFiles = folder.listFiles();
for (final File file : listOfFiles) {
ImageView imageView;
imageView = createImageView(file);
imagecontainer.getChildren().addAll(imageView);
}
}
private ImageView createImageView(final File imageFile) throws FileNotFoundException, FileNotFoundException, FileNotFoundException, FileNotFoundException {
// DEFAULT_THUMBNAIL_WIDTH is a constant you need to define
// The last two arguments are: preserveRatio, and use smooth (slower) resizing
ImageView imageView = null;
try {
final Image image;
image = new Image(new FileInputStream(imageFile), DEFAULT_THUMBNAIL_WIDTH, 0, true, true);
imageView = new ImageView(image);
} catch (FileNotFoundException ex) {
Logger.getLogger(GalleryController.class.getName()).log(Level.SEVERE, null, ex);
}
return imageView;
}
}
kindly help me to resolve my issue. I want to display images one by one as thumbnail view.
You need to create a TilePane and add the ImageView's to it. You can have a ScrollPane if needed. A complete example with double click to create a fullscreen preview is shown below. You can of course do necessary changes for creating a FXML :)
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import javafx.application.Application;
import javafx.event.EventHandler;
import javafx.geometry.Insets;
import javafx.scene.Scene;
import javafx.scene.control.ScrollPane;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.input.MouseButton;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.TilePane;
import javafx.scene.paint.Color;
import javafx.stage.Screen;
import javafx.stage.Stage;
public class ImageGallery extends Application {
Stage stage;
#Override
public void start(Stage primaryStage) throws Exception {
stage = primaryStage;
ScrollPane root = new ScrollPane();
TilePane tile = new TilePane();
root.setStyle("-fx-background-color: DAE6F3;");
tile.setPadding(new Insets(15, 15, 15, 15));
tile.setHgap(15);
String path = "/home/ubuntu/eclipse with liferay/Desktop/imagetest/";
File folder = new File(path);
File[] listOfFiles = folder.listFiles();
for (final File file : listOfFiles) {
ImageView imageView;
imageView = createImageView(file);
tile.getChildren().addAll(imageView);
}
root.setHbarPolicy(ScrollPane.ScrollBarPolicy.NEVER); // Horizontal
root.setVbarPolicy(ScrollPane.ScrollBarPolicy.AS_NEEDED); // Vertical scroll bar
root.setFitToWidth(true);
root.setContent(tile);
primaryStage.setWidth(Screen.getPrimary().getVisualBounds().getWidth());
primaryStage.setHeight(Screen.getPrimary().getVisualBounds()
.getHeight());
Scene scene = new Scene(root);
primaryStage.setScene(scene);
primaryStage.show();
}
private ImageView createImageView(final File imageFile) {
// DEFAULT_THUMBNAIL_WIDTH is a constant you need to define
// The last two arguments are: preserveRatio, and use smooth (slower)
// resizing
ImageView imageView = null;
try {
final Image image = new Image(new FileInputStream(imageFile), 150, 0, true,
true);
imageView = new ImageView(image);
imageView.setFitWidth(150);
imageView.setOnMouseClicked(new EventHandler<MouseEvent>() {
#Override
public void handle(MouseEvent mouseEvent) {
if(mouseEvent.getButton().equals(MouseButton.PRIMARY)){
if(mouseEvent.getClickCount() == 2){
try {
BorderPane borderPane = new BorderPane();
ImageView imageView = new ImageView();
Image image = new Image(new FileInputStream(imageFile));
imageView.setImage(image);
imageView.setStyle("-fx-background-color: BLACK");
imageView.setFitHeight(stage.getHeight() - 10);
imageView.setPreserveRatio(true);
imageView.setSmooth(true);
imageView.setCache(true);
borderPane.setCenter(imageView);
borderPane.setStyle("-fx-background-color: BLACK");
Stage newStage = new Stage();
newStage.setWidth(stage.getWidth());
newStage.setHeight(stage.getHeight());
newStage.setTitle(imageFile.getName());
Scene scene = new Scene(borderPane,Color.BLACK);
newStage.setScene(scene);
newStage.show();
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}
}
}
});
} catch (FileNotFoundException ex) {
ex.printStackTrace();
}
return imageView;
}
public static void main(String[] args) {
launch(args);
}
}
Output
This works great when you resize the Window, making the ScrollPane visible, if required.
Is it somehow possible to render a GUI to a BufferedImage or another kind of memory image without displaying it on a screen ?
I know this will loose all kinds of hardware acceleration, but for a simple GUI that is refreshed only once or twice a second this should not be an issue.
Already tried to get JavaFX to output an image, but i can't find a way to leave out rendering on a screen first. Does anyone know a way to do this with JavaFX or Swing ?
It is no problem to draw a simple GUI myself using simple image manipulations, but then i would have to do it all by hand and using Swing or FX would make it much easier.
Edit:
To make it a bit more clear, i don't have an active display, but i can save an image which then gets displayed through other means. To be exact its a raspberry pi, but without a primary display device with a connected tft display using the GPIO port. So i can't render the UI directly to a display device, but need to create an image that i can save at a specific location. All methods i have tried so far need a primary display device.
Yes, it is possible to render a GUI to an image offscreen.
Here is a sample using JavaFX, with example image output as below:
The example works by rendering the chart to an scene which is not added to any window and no window (Stage in JavaFX terminology) is ever shown. The snapshot method is used to take a snapshot of the node and then ImageIO utilities are used to save the snapshot to disk.
Rendering of the offscreen scene will be hardware accelerated if the underlying hardware/software platform supports it.
import javafx.application.*;
import javafx.collections.*;
import javafx.embed.swing.SwingFXUtils;
import javafx.scene.*;
import javafx.scene.chart.PieChart;
import javafx.scene.image.Image;
import javafx.scene.layout.Region;
import javafx.stage.Stage;
import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.logging.*;
public class OffscreenImageRecorder extends Application {
private static final Logger logger = Logger.getLogger(OffscreenImageRecorder.class.getName());
private static final String IMAGE_TYPE = "png";
private static final String IMAGE_FILENAME = "image." + IMAGE_TYPE;
private static final String WORKING_DIR = System.getProperty("user.dir");
private static final String IMAGE_PATH = new File(WORKING_DIR, IMAGE_FILENAME).getPath();
private final SimpleDateFormat dateFormat = new SimpleDateFormat("HH:mm:ss.SSS");
private final Random random = new Random();
private final int CHART_SIZE = 400;
#Override
public void start(Stage stage) throws IOException {
Parent chart = createChart();
Image image = snapshot(chart);
exportPng(SwingFXUtils.fromFXImage(image, null), IMAGE_PATH);
Platform.exit();
}
private Parent createChart() {
// create a chart.
final PieChart chart = new PieChart();
ObservableList<PieChart.Data> pieChartData =
FXCollections.observableArrayList(
new PieChart.Data("Grapefruit", random.nextInt(30)),
new PieChart.Data("Oranges", random.nextInt(30)),
new PieChart.Data("Plums", random.nextInt(30)),
new PieChart.Data("Pears", random.nextInt(30)),
new PieChart.Data("Apples", random.nextInt(30))
);
chart.setData(pieChartData);
chart.setTitle("Imported Fruits - " + dateFormat.format(new Date()));
// It is important for snapshots that the chart is not animated
// otherwise we could get a snapshot of the chart before the
// data display has been animated in.
chart.setAnimated(false);
chart.setMinSize(Region.USE_PREF_SIZE, Region.USE_PREF_SIZE);
chart.setPrefSize(CHART_SIZE, CHART_SIZE);
chart.setMaxSize(Region.USE_PREF_SIZE, Region.USE_PREF_SIZE);
return chart;
}
private Image snapshot(final Parent sourceNode) {
// Note: if the source node is not in a scene, css styles will not
// be applied during a snapshot which may result in incorrect rendering.
final Scene snapshotScene = new Scene(sourceNode);
return sourceNode.snapshot(
new SnapshotParameters(),
null
);
}
private void exportPng(BufferedImage image, String filename) {
try {
ImageIO.write(image, IMAGE_TYPE, new File(filename));
logger.log(Level.INFO, "Wrote image to: " + filename);
} catch (IOException ex) {
logger.log(Level.SEVERE, null, ex);
}
}
public static void main(String[] args) {
launch(args);
}
}
It's a bit of a hack, but you could create a frame and position it on a invisible location (using Swing in this example):
frame = new JFrame("Invisible frame");
frame.setBounds(-1000, 100, 640, 480);
I am trying to add an image to a JButton and I'm not sure what I'm missing. When I run the following code the button looks exactly the same as if I had created it without any image attribute. Water.bmp is in the root of my project folder.
ImageIcon water = new ImageIcon("water.bmp");
JButton button = new JButton(water);
frame.add(button);
I think that your problem is in the location of the image. You shall place it in your source, and then use it like this:
JButton button = new JButton();
try {
Image img = ImageIO.read(getClass().getResource("resources/water.bmp"));
button.setIcon(new ImageIcon(img));
} catch (Exception ex) {
System.out.println(ex);
}
In this example, it is assumed that image is in src/resources/ folder.
#Rogach
and you may like to add:
// to remote the spacing between the image and button's borders
button.setMargin(new Insets(0, 0, 0, 0));
// to add a different background
button.setBackground( ... );
// to remove the border
button.setBorder(null);
It looks like a location problem because that code is perfectly fine for adding the icon.
Since I don't know your folder structure, I suggest adding a simple check:
File imageCheck = new File("water.bmp");
if(imageCheck.exists())
System.out.println("Image file found!")
else
System.out.println("Image file not found!");
This way if you ever get your path name wrong it will tell you instead of displaying nothing. Exception should be thrown if file would not exist, tho.
You put your image in resources folder and use follow code:
JButton btn = new JButton("");
btn.setIcon(new ImageIcon(Class.class.getResource("/resources/img.png")));
public class ImageButton extends JButton {
protected ImageButton(){
}
#Override
public void paint(Graphics g) {
Graphics2D g2 = (Graphics2D) g;
Image img = Toolkit.getDefaultToolkit().getImage("water.bmp");
g2.drawImage(img, 45, 35, this);
g2.finalize();
}
}
OR use this code
class MyButton extends JButton {
Image image;
ImageObserver imageObserver;
MyButtonl(String filename) {
super();
ImageIcon icon = new ImageIcon(filename);
image = icon.getImage();
imageObserver = icon.getImageObserver();
}
public void paint( Graphics g ) {
super.paint( g );
g.drawImage(image, 0 , 0 , getWidth() , getHeight() , imageObserver);
}
}
I did only one thing and it worked for me .. check your code is this method there ..
setResizable(false);
if it false make it true and it will work just fine ..
I hope it helped ..
buttonB.setIcon(new ImageIcon(this.getClass().getResource("imagename")));
//paste required image on C disk
JButton button = new JButton(new ImageIcon("C:water.bmp");
This code work for me:
BufferedImage image = null;
try {
URL file = getClass().getResource("water.bmp");
image = ImageIO.read(file);
} catch (IOException ioex) {
System.err.println("load error: " + ioex.getMessage());
}
ImageIcon icon = new ImageIcon(image);
JButton quitButton = new JButton(icon);
For example if you have image in folder res/image.png you can write:
try
{
ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
InputStream input = classLoader.getResourceAsStream("image.png");
// URL input = classLoader.getResource("image.png"); // <-- You can use URL class too.
BufferedImage image = ImageIO.read(input);
button.setIcon(new ImageIcon(image));
}
catch(IOException e)
{
e.printStackTrace();
}
In one line:
try
{
button.setIcon(new ImageIcon(ImageIO.read(Thread.currentThread().getContextClassLoader().getResourceAsStream("image.png"))));
}
catch(IOException e)
{
e.printStackTrace();
}
If the image is bigger than button then it will not shown.
eclipse example:
After reading the above, it still took me more research to understand, where and how to place image resources, using eclipse.
The outcome: in eclipse you need to store images underneath any "Source Folder" (such as "src") or below in a "Folder".
You create both by right-clicking on your project, "New"->"Source Folder" or "New"->"Folder". Any folder name is fine. Examples for "<Source Folder>/<image Folder>" are "src/images" or "resource/img".
Here's some fully functioning sample code, which expects two button images, "Button-Image-Up.png" and "Button-Image-Down.png" in folder "images":
import javax.swing.JDialog;
import java.awt.BorderLayout;
import java.awt.FlowLayout;
import java.awt.Image;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
#SuppressWarnings("serial")
public class ImageButtonDlg extends JDialog {
// define button images and fall-back text
private static gstrTxt="<Button Fall-back Text>"; // in case image does not load
private static String gstrImgUp="Button-Image-Up.png"; // regular image
private static String gstrImgDown="Button-Image-Down.png"; // button pressed image
private static String gstrImgFolder="images"; // image folder, "/images" is also fine
public static void main(String[] args) {
ImageButtonDlg dialog = new ImageButtonDlg();
dialog.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
dialog.setVisible(true);
}
/**
* Create the dialog.
*/
public ImageButtonDlg() {
initializeDialog();
}
/**
* Create a new ImageIcon from an image resource.
* The input can be:
* - an image file name, e.g. <image.png>
* - a relative path, e.g. <image/image.png>
* - an absolute path, e.g. </home/user/dev/image.png>
* In eclipse, images can be stored below any project "Source folder",
* such as "src".
* ├── src
* │ ├── img1.png
* │ └── images
* │ └── img2.png
* ├── resources
* │ ├── img3.png
* │ └── images
* │ └── img4.png
* └── img5.png
* In above example img1.png to img4.png are found by
* image file name or relative path
* However, img5 is stored in the project root folder and
* needs an absolute path.
*
* #param strImagePath - image filename, absolute path or relative path
* #return new ImageIcon or 'null' if load fails
*/
public static ImageIcon getResourceImageIcon(String strFilepath) {
ClassLoader loader = null;
URL url = null;
Image img=null;
ImageIcon imgIcon=null;
loader = ImageButtonDlg.class.getClassLoader();
System.out.println(loader.toString());
try { // file location: <a relative path>
url = loader.getResource("images/"+strFilepath);
if(url==null) {
System.out.printf("ImageButtonDlg.class.getResource(%s)=>null\n", "images/"+strFilepath);
}
} catch (Exception e0) {
e0.printStackTrace();
}
if(url==null) {
try { // file location: <image filename>
url = loader.getResource(strFilepath);
if(url==null) {
System.out.printf("Util.class.getResource(%s)=>null\n", strFilepath);
}
} catch (Exception e1) {
e1.printStackTrace();
}
}
try {
img = ImageIO.read(url);
} catch (Exception e2) {
e2.printStackTrace();
System.exit(0);
}
if (img!=null){
imgIcon = new ImageIcon(img);
}
return imgIcon;
}
/**
* Create JButton with Image
* In case Image load fails, we create a JButton with text
* #param strImgPath - path to Image
* #param strAltText - fall-back text
* #return
*/
public static JButton getNewJButtonWithImageIcon(String strImgPath, String strAltText) {
JButton btnReturn = null;
ImageIcon imgIcon = getResourceImageIcon(strImgPath);
if (imgIcon!=null){
btnReturn = new JButton(imgIcon);
}
else {
btnReturn = new JButton(strAltText);
}
return btnReturn;
}
/**
* Image button was pressed, display a message box
*/
private void actionImageButtonPressed() {
try {
JOptionPane.showMessageDialog(null, "Image Button was pressed", "Info", JOptionPane.INFORMATION_MESSAGE);
}
catch (Exception e) {
; // ignore
}
}
/**
* Initialize the dialog
* add a button panel and the image button to the window/content pane
*/
private void initializeDialog()
{
this.setTitle("Image Button Example");
this.setResizable(false);
this.setBounds(200, 200, 699, 601);
JPanel panelButton = new JPanel();
panelButton.setLayout(new FlowLayout(FlowLayout.RIGHT)); // all buttons in a row
getContentPane().add(panelButton, BorderLayout.SOUTH); // button pane at the bottom of the window
// create the Image Button
JButton btnImageButton = getNewJButtonWithImageIcon(gstrImgUp, gstrTxt);
btnImageButton.setToolTipText("<Explain what pressing the Button does>");
btnImageButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
actionImageButtonPressed();// The Action
}
});
// load button image when button clicked/released
btnImageButton.addMouseListener((MouseListener) new MouseAdapter() {
public void mousePressed(MouseEvent e) {
btnImageButton.setIcon(getResourceImageIcon(gstrImgDown));
}
public void mouseReleased(MouseEvent e) {
btnImageButton.setIcon(getResourceImageIcon(gstrImgUp));
}
});
btnImageButton.setActionCommand("ImageButtonAction");
// add button to button panel
panelButton.add(btnImageButton);
}
}
Have Fun!
Volker Fröhlich
P.S.:
Perhaps someone can share additional practical experience.
In eclipse "WindowBuilder Editor" such image buttons are shown, but they cannot be accessed - is there some workaround?
What is the NetBeans approach, if any different?