我想将纹理应用于自定义形状.我认为这会奏效:
.myTextureShape { -fx-shape: "M0 0 L0 50 L25 25 L50 50 L50 0 Z"; -fx-background-image: url("resources/texture_bg.png"); -fx-background-repeat: repeat; }
但事实并非如此!我得到了正确的形状,但没有纹理.我所有其他区域都正确纹理化,所以我知道语法是正确的.我想这是因为它们默认是矩形的.
如果我使用以下样式:
.myTextureShape { -fx-shape: "M0 0 L0 50 L25 25 L50 50 L50 0 Z"; -fx-background-color: red; }
然后我得到一个正确的红色背景.
如果两个属性都不兼容,如何将纹理应用于自定义SVG-pathed-shape?
P.S:我的纹理PNG文件,是一个小的10 * 10光栅,我重复填充我的区域.
解决方法
就我而言-fx-shape和-fx-background-image不能一起工作.
JavaFX CSS提供了许多样式选项……但是有一些限制,有些东西只能通过编程实现. JavaFX CSS使用impl_setShape()将Region类粗略定义为已定义的形状(在api中市场已弃用,但您仍然可以在javafx 2.2中尝试它 – 我目前正在使用它).添加背景图像会忽略形状并填充整个窗格/区域,如果使用addChildren将ImageView对象添加到其中,也会发生相同的情况.所以 – css字符串不会转换为您想要的结果.
JavaFX CSS提供了许多样式选项……但是有一些限制,有些东西只能通过编程实现. JavaFX CSS使用impl_setShape()将Region类粗略定义为已定义的形状(在api中市场已弃用,但您仍然可以在javafx 2.2中尝试它 – 我目前正在使用它).添加背景图像会忽略形状并填充整个窗格/区域,如果使用addChildren将ImageView对象添加到其中,也会发生相同的情况.所以 – css字符串不会转换为您想要的结果.
所以我可以想到至少2种将模式应用于自定义SVGPath形状的方法.
我将使用的是使用ImagePattern完成的.首先建立这样的形状
SVGPath shape = new SVGPath(); shape.setContent("M0 0 L0 50 L25 25 L50 50 L50 0 Z");
或使用形状构建器
SVGPath shape = SVGPathBuilder.create() .content("M0 0 L0 50 L25 25 L50 50 L50 0 Z") .build();
然后将图像模式设置为填充
Image img = new Image("myjavafxapp/resources/texture_bg.png"); shape.setFill(new ImagePattern(img,10,false));
另一种方法是使用裁剪(将自定义形状剪辑添加到窗格中,并在css样式中设置-fx-background-image),这看起来有点像这样
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);
其中一个应该做的伎俩 – 你的纹理背景你的形状.这相当于您对具有样式的Region或Pane类的期望
.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; }
因此,SVGPath形状就像所有不可调整的Shape类一样,与Region / Pane相比,这就是我将-fx-scale-shape属性设置为false的原因.您使用它的方式是使用默认设置 – 将其设置为true – 这使得形状填充整个父对象…我猜这也是您想要的结果. …现在又有多种方法可以将形状缩放到父对象.
我使用Group来嵌入形状并使用方法转换组(图像大小需要在ImagePattern中调整,以便纹理不随形状缩放).我正在添加一个微小的工作应用程序,如果我记得所有内容,我在上面的示例中看到了这个应用程序. (如果您希望形状按比例缩放,则在addScale方法中使用相同的比例因子而不是scalex和sclaey)
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 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,10/scalex,10/scaley,false)); } } public static void main(String[] args) { launch(args); } }