En ce qui me concerne -fx-shape
y -fx-background-image
ne travaillent pas ensemble. JavaFX CSS offre un grand nombre d'options de style ... mais il y a quelques limitations et certaines choses ne sont possibles qu'avec la programmation. JavaFX CSS utilise impl_setShape()
pour faire correspondre la classe Region à la forme définie (ce qui est considéré comme déprécié dans l'api mais vous pouvez toujours l'essayer dans javafx 2.2 - que j'utilise en ce moment). L'ajout de l'image de fond ignore la forme et remplit l'ensemble du panneau/de la région, la même chose se produit si vous utilisez addChildren pour ajouter des objets ImageView. Donc - la chaîne css ne se traduira pas par le résultat que vous souhaitez.
Je peux donc penser à au moins deux façons d'appliquer un motif à une forme SVGPath personnalisée. Celle que j'utiliserais est faite avec ImagePattern. D'abord, construisez la forme comme ceci
SVGPath shape = new SVGPath();
shape.setContent("M0 0 L0 50 L25 25 L50 50 L50 0 Z");
ou en utilisant le shape builder
SVGPath shape = SVGPathBuilder.create()
.content("M0 0 L0 50 L25 25 L50 50 L50 0 Z")
.build();
et ensuite définir le motif de l'image comme remplissage
Image img = new Image("myjavafxapp/resources/texture_bg.png");
shape.setFill(new ImagePattern(img,0,0,10,10,false));
Une autre solution consisterait à utiliser l'écrêtage (en ajoutant un écrêtage de forme personnalisée à un volet avec le paramètre -fx-background-image défini dans le style css), ce qui ressemblerait à ceci
Pane test = new Pane();
test.setStyle(" -fx-background-image: url(\"myjavafxapp/res/index.jpeg\");");
SVGPath shape = new SVGPath();
shape.setContent("M0 0 L0 50 L25 25 L50 50 L50 0 Z");
test.setClip(shape);
L'une d'entre elles devrait faire l'affaire - vous obtenez votre forme avec l'arrière-plan texturé. C'est l'équivalent de ce que vous attendez d'une classe Region ou Pane avec le style
.myTextureShape {
-fx-shape: "M0 0 L0 50 L25 25 L50 50 L50 0 Z";
-fx-scale-shape: false;
-fx-background-image: url("myjavafxapp/resources/texture_bg.png");
-fx-background-repeat: repeat;
}
Ainsi, la forme SVGPath est, comme toutes les classes Shape, non redimensionnable, contrairement à Region/Pane, c'est pourquoi j'ai défini ici l'attribut -fx-scale-shape
à false. Dans votre cas, il s'agissait du paramètre par défaut, c'est-à-dire la valeur true, qui fait que la forme remplit tout l'objet parent... Je suppose que c'est également le résultat que vous souhaitez. ... il y a maintenant plusieurs façons de mettre la forme à l'échelle de l'objet parent.
J'ai réussi à le faire fonctionner en utilisant Group pour intégrer la forme et avec une méthode traduisant le groupe (la taille de l'image doit être ajustée dans ImagePattern, afin que la texture ne soit pas mise à l'échelle avec la forme). J'ajoute une petite application fonctionnelle, que je voyais sur l'exemple ci-dessus si je me souviens bien de tout. (si vous souhaitez que la forme soit mise à l'échelle proportionnellement, vous utilisez le même facteur d'échelle au lieu de scalex et sclaey dans la méthode addScale)
package myjavafxapp;
import javafx.application.Application;
import javafx.application.Platform;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.scene.Group;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.layout.Pane;
import javafx.scene.layout.StackPane;
import javafx.scene.shape.SVGPath;
import javafx.scene.shape.SVGPathBuilder;
import javafx.scene.image.Image;
import javafx.scene.paint.*;
import javafx.scene.transform.Scale;
import javafx.scene.transform.Translate;
import javafx.stage.Stage;
/**
* @author martint
*/
public class MyJavaFXApp extends Application {
private final static String svg = "M0 0 L0 50 L25 25 L50 50 L50 0 Z";
private SVGPath shape;
private Image img;
private Pane resizePane;
private Group shapeGroup;
private Node content;
@Override
public void start(final Stage primaryStage) {
//build the SVGPath shape
shape = SVGPathBuilder.create().content(svg).build();
img = new Image("myjavafxapp/res/index.jpeg");
resizePane = new Pane();
shapeGroup = new Group();
resizePane.getChildren().add(shapeGroup);
StackPane root = new StackPane();
root.getChildren().add(resizePane);
Scene scene = new Scene(root, 200, 200);
primaryStage.setScene(scene);
primaryStage.show();
//fill node content
content = nodeCont();
shapeGroup.getChildren().add(content);
//resizing listening
resizePane.widthProperty().addListener(new ChangeListener<Number>(){
@Override
public void changed(ObservableValue<? extends Number> observable, Number oldValue, Number newValue) {
addScaling();
}});
resizePane.heightProperty().addListener(new ChangeListener<Number>(){
@Override
public void changed(ObservableValue<? extends Number> observable, Number oldValue, Number newValue) {
addScaling();
}});
Platform.runLater(new Runnable() {
@Override
public void run() {
addScaling();
}
});
}
private Node nodeCont() {
Group cont = new Group();
cont.getChildren().add(shape);
return cont;
}
private void addScaling() {
shapeGroup.getTransforms().clear();
//shape boundary
double cx = content.getBoundsInParent().getWidth();
double cy = content.getBoundsInParent().getHeight();
//resizePane boundary
double px = resizePane.getWidth();
double py = resizePane.getHeight();
//if pane set
if (px > 0.0 && py > 0.0) {
//scale
double scalex = px/cx;
double scaley = py/cy;
//center
double centerx = 0.5 * (px - cx*scalex);
double centery = 0.5 * (py - cy*scaley);
//transform
shapeGroup.getTransforms().add(new Translate(centerx, centery));
shapeGroup.getTransforms().add(new Scale(scalex, scaley));
shape.setFill(new ImagePattern(img,0,0,10/scalex,10/scaley,false));
}
}
public static void main(String[] args) {
launch(args);
}
}