'JavaFX - create custom button with image
I would like to create a custom button, that has two states pressed or not, like a toggle button. I have got two images to do this (pressed and not pressed), so how can i create the button and display it with my images ? The button must take the size of the image.
I am not using FXML.
Thank you for helping.
Solution 1:[1]
You just need to create your own class inherited from parent. Place an ImageView on that, and on the mousedown and mouse up events just change the images of the ImageView.
public class ImageButton extends Parent {
private static final Image NORMAL_IMAGE = ...;
private static final Image PRESSED_IMAGE = ...;
private final ImageView iv;
public ImageButton() {
this.iv = new ImageView(NORMAL_IMAGE);
this.getChildren().add(this.iv);
this.iv.setOnMousePressed(new EventHandler<MouseEvent>() {
public void handle(MouseEvent evt) {
iv.setImage(PRESSED_IMAGE);
}
});
// TODO other event handlers like mouse up
}
}
Solution 2:[2]
A combination of previous 2 answers did the trick. Thanks. A new class which inherits from Button. Note: updateImages() should be called before showing the button.
import javafx.event.EventHandler;
import javafx.scene.control.Button;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.input.MouseEvent;
public class ImageButton extends Button {
public void updateImages(final Image selected, final Image unselected) {
final ImageView iv = new ImageView(selected);
this.getChildren().add(iv);
iv.setOnMousePressed(new EventHandler<MouseEvent>() {
public void handle(MouseEvent evt) {
iv.setImage(unselected);
}
});
iv.setOnMouseReleased(new EventHandler<MouseEvent>() {
public void handle(MouseEvent evt) {
iv.setImage(selected);
}
});
super.setGraphic(iv);
}
}
Solution 3:[3]
For some reason, when I have many of these on a scene (think toolbars), using Buttons always proved to be "sluggish" in their handling of image swaps during clicks, and re-sizing on the fly was extremely slow and would even sometimes cause the Java virtual machine itself to dump out.
Using the ImageView objects themselves has always proven to be extremely responsive, no matter how many I have on a Scene. They swap out the images instantly, they can be resized on the fly with instantaneous response and they feel very natural to use, unlike the Buttons which tend to feel ... 'resistive' in a way.
Here is how I do it:
public void buildImageButtons() {
double iconSize = 50;
Image unSelectedOne = new Image(Main.class.getResourceAsStream("UnselectedImageOne.png"));
Image selectedOne = new Image(Main.class.getResourceAsStream("SelectedImageOne.png"));
Image unSelectedTwo = new Image(Main.class.getResourceAsStream("UnselectedImageTwo.png"));
Image selectedTwo = new Image(Main.class.getResourceAsStream("SelectedImageTwo.png"));
ImageView ivOne = newImageView(unSelectedOne, selectedOne, iconSize);
ImageView ivTwo = newImageView(unSelectedTwo, selectedTwo, iconSize);
ivOne.setOnMouseClicked(e -> methodOne());
ivTwo.setOnMouseClicked(e -> methodTwo());
}
private ImageView newImageView(Image unselected, Image selected, double iconSize) {
ImageView iv = new ImageView(unselected);
iv.setPreserveRatio(true);
iv.setFitWidth(iconSize);
iv.setOnMousePressed(e->{
iv.setImage(selected);
});
iv.setOnMouseReleased(e->{
iv.setImage(unselected);
});
return iv;
}
private void methodOne() {
System.out.println("Image One Clicked");
}
private void methodTwo() {
System.out.println("Image Two Clicked");
}
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | dipacs |
| Solution 2 | |
| Solution 3 | Michael Sims |
