Issue
As answered in this thread, ImageViews can be clipped to achieve corner rounding (Corner rounding of imageViews cannot be achieved with CSS). However, I am trying to have different corner radii, very much like described by this bit of CSS:
.background {
-fx-background-radius: 64 0 16 0;
}
What i want the image to look like (Image = black area) is pretty much:
The problem I am currently facing is that it is not possible to clip imageViews
with a VBox
, for instance. I could clip, however, the imageView
with a Rectangle
, but this again, does not give me the possibility to have different corner radii.
How could I achieve the same effect as the above CSS code (which of course does not work with an imageView) and have an image have different corners?
Solution
Clip ImageView with Path
In this approach an ImageView
is clipped with a Path
. That path will adapt at FitWidth and FitHeight values of each imageView passed to getClip
method . The second and third arguments passed are values to calculate radius of top and bottom round corner based on Fitheight .
getClip
method will draw a path like so :
This is a single class javafx app you can try
App.java
public class App extends Application {
@Override
public void start(Stage stage) {
ImageView imageView = new ImageView("https://ioppublishing.org/wp-content/uploads/2017/03/cat-web-cc0.jpg");
imageView.setFitHeight(300);
imageView.setFitWidth(300);
imageView.setClip(getClip(imageView, 0.1,0.3));
ImageView imageView1 = new ImageView("https://ioppublishing.org/wp-content/uploads/2017/03/cat-web-cc0.jpg");
imageView1.setFitHeight(400);
imageView1.setFitWidth(400);
imageView1.setClip(getClip(imageView1, 0.2,0.3));
VBox vBox = new VBox(imageView, imageView1);
vBox.setSpacing(20);
vBox.setPadding(new Insets(20));
vBox.setAlignment(Pos.CENTER);
vBox.setFillWidth(true);
var scene = new Scene(new StackPane(vBox), 1024, 800);
stage.setScene(scene);
stage.setTitle("clipping with path");
stage.show();
}
public static void main(String[] args) {
launch();
}
private Node getClip(ImageView imageView, double radiusTop,double radiusBot) {
Path clip;
double height = imageView.getFitHeight();
double width = imageView.getFitWidth();
double radius1 = height * radiusTop;
double radius2 = height * radiusBot;
clip = new Path(new MoveTo(0, radius1), new ArcTo(radius1, radius1, 0, radius1, 0, false, true),
new HLineTo(width),
new VLineTo(height - radius2),
new ArcTo(radius2, radius2, 0, width - radius2, height, false, true),
new HLineTo(0));
clip.setFill(Color.ALICEBLUE);
return clip;
}
}
App.java
public class App extends Application {
@Override
public void start(Stage stage) {
ImageView imageView = new ImageView("https://ioppublishing.org/wp-content/uploads/2017/03/cat-web-cc0.jpg");
imageView.setFitHeight(300);
imageView.setFitWidth(300);
imageView.setClip(getClip(imageView, 0.3, 0.1, 0.2, 0.1));
ImageView imageView1 = new ImageView("https://ioppublishing.org/wp-content/uploads/2017/03/cat-web-cc0.jpg");
imageView1.setFitHeight(400);
imageView1.setFitWidth(400);
imageView1.setClip(getClip(imageView1, 0.3, 0.2, 0.1, 0.2));
VBox vBox = new VBox(imageView, imageView1);
vBox.setSpacing(20);
vBox.setPadding(new Insets(20));
vBox.setAlignment(Pos.CENTER);
vBox.setFillWidth(true);
var scene = new Scene(new StackPane(vBox), 1024, 800);
stage.setScene(scene);
stage.setTitle("clipping with path");
stage.show();
}
public static void main(String[] args) {
launch();
}
private Node getClip(ImageView imageView, double topLeft, double topRight, double bottomLeft, double bottomRight) {
Path clip;
double height = imageView.getFitHeight();
double width = imageView.getFitWidth();
double radius1 = height * topLeft;
double radius2 = height * topRight;
double radius3 = height * bottomLeft;
double radius4 = height * bottomRight;
clip = new Path(new MoveTo(0, radius1),
new ArcTo(radius1, radius1, 0, radius1, 0, false, true),
new HLineTo(width - radius2),
new ArcTo(radius2, radius2, 0, width, radius2, false, true),
new VLineTo(height - radius4),
new ArcTo(radius4, radius4, 0, width - radius4, height, false, true),
new HLineTo(radius3),
new ArcTo(radius3, radius3, 0, 0, height - radius3, false, true));
clip.setFill(Color.ALICEBLUE);
return clip;
}
}
Answered By - Giovanni Contreras
Answer Checked By - Candace Johnson (JavaFixing Volunteer)