I can make a rectangle with JavFX like this:
Rectangle node2 = RectangleBuilder.create()
.x(-100)
.y(-100)
.width(200)
.height(200)
.fill(Color.GREEN)
.build();
but how can I make it use a texture instead of just a color?
TIA
The original answer was written many years ago and uses a Builder pattern which was removed from the JavaFX API.
Additionally, new features have been added to the JavaFX API over the years, offering more options.
So I have updated this answer with new information.
Regardless, if you find this question you are probably looking for an ImagePattern
to apply to a 2D shape, as the original asker was looking for.
Rectangle patternWithNoRepeats = new Rectangle(
image.getWidth(), image.getHeight(),
new ImagePattern(image)
);
2D "textures" are Paint
.
There are various kinds of paint, which can be seen from the subclasses of paint:
Color
: A solid color.ImagePattern
: A (possibly repeating) pattern based on an image. For example a repeating image of a wood grain pattern. This is what most people think of as a "texture".LinearGradient
and RadialGradient
: Gradiated color blends.Anything that accepts paint as an argument (e.g. fills and strokes of shapes, backgrounds of regions, etc) can use any of the paint types mentioned above.
3D textures are used in Material
. The only material provided in JavaFX 23 is a PhongMaterial
. The javadoc for this class is good, and I encourage you to read it if you intend to do any 3D work.
The basic way to map a 2D image onto a 3D object is to apply the Image as a diffuseMap
.
A TriangleMesh
can project portions of the 2D diffuse image onto a 3D model using uv coordinates, as explained in:
Materials are based on images and colors and can encode additional information to supplement a flat image, such as bump maps, spectral highlights, self-illumination, etc.
This example demonstrates using textures by:
TextureApp.java
import javafx.application.Application;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.layout.Background;
import javafx.scene.layout.HBox;
import javafx.scene.paint.*;
import javafx.scene.shape.Rectangle;
import javafx.stage.Stage;
import javafx.scene.image.Image;
import java.util.Objects;
public class TextureApp extends Application {
private static final String IMAGE_FILE = "Dragon-icon.png";
private static final double NUM_REPEATS = 2;
@Override
public void start(Stage stage) {
Image image = new Image(
getResourceURL(IMAGE_FILE)
);
Rectangle patternWithNoRepeats = new Rectangle(
image.getWidth(), image.getHeight(),
new ImagePattern(image)
);
patternWithNoRepeats.setStroke(Color.PALEGREEN);
patternWithNoRepeats.setStrokeWidth(4);
Rectangle patternWithRepeats = new Rectangle(
image.getWidth() * NUM_REPEATS, image.getHeight() * NUM_REPEATS,
new ImagePattern(image, 0, 0, 1 / NUM_REPEATS, 1 / NUM_REPEATS, true)
);
patternWithRepeats.setStroke(Color.PALETURQUOISE);
patternWithRepeats.setStrokeWidth(4);
HBox layout = new HBox(10, patternWithNoRepeats, patternWithRepeats);
layout.setAlignment(Pos.CENTER);
layout.setPadding(new Insets(10));
layout.setBackground(
Background.fill(
new LinearGradient(
0, 0, 0, 1,
true,
CycleMethod.NO_CYCLE,
new Stop[] {
new Stop(0, Color.CORAL),
new Stop(1, Color.CORNFLOWERBLUE)
}
)
)
);
stage.setScene(new Scene(layout));
stage.show();
}
private static String getResourceURL(String filename) {
return Objects.requireNonNull(
TextureApp.class.getResource(
filename
)
).toExternalForm();
}
}
Dragon-icon.png
Set the fill to an ImagePattern
Rectangle node2 =
RectangleBuilder.create()
.x(-100)
.y(-100)
.width(200)
.height(200)
.fill(
new ImagePattern(
new Image("file:flower.png"), 0, 0, 1, 1, true
)
)
.build();
There are additional samples in the ImagePattern javadoc.
For JavaFX8, you will also be able to do this via css.