JavaFX 将 ImageView 裁剪为 AnchorPane 中的椭圆
Posted
技术标签:
【中文标题】JavaFX 将 ImageView 裁剪为 AnchorPane 中的椭圆【英文标题】:JavaFX Clipping an ImageView to an Ellipse within an AnchorPane 【发布时间】:2014-09-10 08:05:51 【问题描述】:我一直在构建一个应用程序,我想在椭圆内显示一个大图像以模仿天文馆的屋顶。
使用 myImageView.setClip(myEllipse)
将 ImageView 显示图像剪辑到椭圆上一直运行良好,直到我添加椭圆的 AnchorPane 的应用程序的最后一个版本似乎不欣赏我在其中剪辑图像。
myImageView.setClip(myEllipse)
行的错误如下:
原因:
java.lang.IllegalArgumentException:节点的剪辑设置为不正确的值 (节点已连接,节点 = ImageView@a13b0a6,剪辑 = ObjectProperty [bean: ImageView@a13b0a6, name: clip, value: null])。
我的理解是我在场景图中创建了某种循环,但我不知道在哪里。
这是我的代码(整个界面是“硬编码”的)
package opinarium3;
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import javafx.application.Application;
import javafx.beans.property.DoubleProperty;
import javafx.beans.property.SimpleDoubleProperty;
import javafx.event.EventHandler;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.TextArea;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.AnchorPane;
import javafx.scene.layout.HBox;
import javafx.scene.layout.Pane;
import javafx.scene.layout.VBox;
import static javafx.scene.layout.VBox.setMargin;
import javafx.scene.shape.Ellipse;
import javafx.scene.text.Font;
import javafx.stage.Stage;
/**
*
* @author Admin
*/
public class Opinarium3 extends Application
private Ellipse ceiling;
private ImageView ceiling_image;
private VBox nav;
private HBox buttonSet;
private Label presentation_title;
private TextArea info;
private Button previous;
private Button comment;
private Button next;
private double sx;
private double sy;
private DoubleProperty coordX = new SimpleDoubleProperty(0);
private DoubleProperty coordY = new SimpleDoubleProperty(0);
@Override
public void start(Stage primaryStage) throws IOException
AnchorPane root = new AnchorPane();
Scene primaryScene = new Scene(root, 900, 800);
primaryScene.getStylesheets().add(Opinarium3.class.getResource("Opinarium3.css").toExternalForm());
initializeCeiling(root);
initializeNav(root);
initializeContent();
initializePrimaryStage(primaryStage, primaryScene);
primaryStage.show();
private void initializePrimaryStage(Stage primaryStage, Scene primaryScene)
primaryStage.setTitle("Planetario de San José - Cartelera de Presentaciones");
primaryStage.setScene(primaryScene);
primaryStage.setWidth(900);
primaryStage.setHeight(800);
primaryStage.minHeightProperty().setValue(800);
primaryStage.minWidthProperty().setValue(900);
/**
* @param args the command line arguments
*/
public static void main(String[] args)
launch(args);
private void initializeCeiling(AnchorPane root)
ceiling = new Ellipse();
ceiling.centerXProperty().bind(root.widthProperty().multiply(0.5));
ceiling.centerYProperty().setValue(0);
ceiling.radiusXProperty().bind(root.widthProperty().multiply(0.8));
ceiling.radiusYProperty().bind(root.heightProperty().multiply(0.6));
root.getChildren().add(ceiling);
private void initializeNav(AnchorPane root)
nav = new VBox();
initializeControls(nav);
AnchorPane.setBottomAnchor(nav, 20.0);
AnchorPane.setLeftAnchor(nav, 120.0);
AnchorPane.setRightAnchor(nav, 120.0);
root.getChildren().add(nav);
private void initializeControls(VBox nav)
info = new TextArea();
setMargin(info, new Insets(10, 0, 0, 0));
info.setWrapText(true);
info.setEditable(false);
buttonSet = new HBox();
initializeButtonSet(nav);
presentation_title = new Label("Título de la Presentación");
presentation_title.setId("titulo");
nav.alignmentProperty().setValue(Pos.CENTER);
nav.getChildren().addAll(presentation_title, info, buttonSet);
private void initializeButtonSet(VBox nav)
previous = new Button("<");
comment = new Button("Doy mi opinión");
comment.setId("comment_button");
next = new Button(">");
buttonSet.spacingProperty().bind(nav.widthProperty().multiply(0.15));
buttonSet.setAlignment(Pos.CENTER);
setMargin(buttonSet, new Insets(10, 0, 0, 0));
buttonSet.getChildren().addAll(previous, comment, next);
private void initializeContent() throws IOException
try
BufferedReader br = new BufferedReader(new FileReader("src/opinarium3/media/joyas/joyas.txt"));
String title = br.readLine();
String length = br.readLine();
String description = br.readLine();
this.presentation_title.setText(title);
this.info.setText("\n"+description+"\n\nDuración: "+length);
br.close();
ceiling_image = new ImageView(new Image(Opinarium3.class.getResourceAsStream("media/joyas/joyas.jpg")));
ceiling_image.setClip(ceiling);
/*
ceiling_image.setOnMousePressed(new EventHandler<MouseEvent>()
@Override
public void handle(MouseEvent t)
sx = t.getSceneX() - coordX.doubleValue();
sy = t.getSceneY() - coordY.doubleValue();
);
ceiling_image.setOnMouseDragged(new EventHandler<MouseEvent>()
@Override
public void handle(MouseEvent t)
if(t.getSceneX() - sx < 0)
coordX.setValue(t.getSceneX() - sx);
if(t.getSceneY() - sy < 0)
coordY.setValue(t.getSceneY() - sy);
);
ceiling_image.xProperty().bind(coordX);
ceiling_image.yProperty().bind(coordY);
*/
catch(IOException e)
【问题讨论】:
对于您的下一个问题,请尝试将代码发布为mcve;即仍然可执行的最小代码,不依赖于本地文件并且只有足够的代码来证明问题。最重要的是,不要在不打印或重新抛出异常的情况下将异常吞入 catch 块中。谢谢 我明白...我会尽量记住所有这些。感谢您的观察。 【参考方案1】:您只能在场景中使用该形状一次,不能将其设置为剪辑并添加为元素的子元素。
您正在将剪辑添加到场景中,而不是正在剪辑到场景中的项目。
import javafx.application.Application;
import javafx.geometry.*;
import javafx.scene.Scene;
import javafx.scene.control.*;
import javafx.scene.image.*;
import javafx.scene.layout.*;
import javafx.scene.shape.Ellipse;
import javafx.stage.Stage;
import static javafx.scene.layout.VBox.setMargin;
public class Opinarium3 extends Application
private Ellipse ceiling;
private ImageView ceiling_image;
private VBox nav;
private HBox buttonSet;
private Label presentation_title;
private TextArea info;
private Button previous;
private Button comment;
private Button next;
@Override
public void start(Stage primaryStage)
AnchorPane root = new AnchorPane();
Scene primaryScene = new Scene(root, 900, 800);
initializeCeiling(root);
initializeNav(root);
initializeContent(root);
initializePrimaryStage(primaryStage, primaryScene);
primaryStage.show();
private void initializePrimaryStage(Stage primaryStage, Scene primaryScene)
primaryStage.setTitle("Planetario de San José - Cartelera de Presentaciones");
primaryStage.setScene(primaryScene);
primaryStage.setWidth(900);
primaryStage.setHeight(800);
primaryStage.minHeightProperty().setValue(800);
primaryStage.minWidthProperty().setValue(900);
public static void main(String[] args)
launch(args);
private void initializeCeiling(AnchorPane root)
ceiling = new Ellipse();
ceiling.centerXProperty().bind(root.widthProperty().multiply(0.5));
ceiling.centerYProperty().setValue(0);
ceiling.radiusXProperty().bind(root.widthProperty().multiply(0.8));
ceiling.radiusYProperty().bind(root.heightProperty().multiply(0.6));
private void initializeNav(AnchorPane root)
nav = new VBox();
initializeControls(nav);
AnchorPane.setBottomAnchor(nav, 20.0);
AnchorPane.setLeftAnchor(nav, 120.0);
AnchorPane.setRightAnchor(nav, 120.0);
root.getChildren().add(nav);
private void initializeControls(VBox nav)
info = new TextArea();
setMargin(info, new Insets(10, 0, 0, 0));
info.setWrapText(true);
info.setEditable(false);
buttonSet = new HBox();
initializeButtonSet(nav);
presentation_title = new Label("Título de la Presentación");
presentation_title.setId("titulo");
nav.alignmentProperty().setValue(Pos.CENTER);
nav.getChildren().addAll(presentation_title, info, buttonSet);
private void initializeButtonSet(VBox nav)
previous = new Button("<");
comment = new Button("Doy mi opinión");
comment.setId("comment_button");
next = new Button(">");
buttonSet.spacingProperty().bind(nav.widthProperty().multiply(0.15));
buttonSet.setAlignment(Pos.CENTER);
setMargin(buttonSet, new Insets(10, 0, 0, 0));
buttonSet.getChildren().addAll(previous, comment, next);
private void initializeContent(AnchorPane root)
Image image = new Image(
"http://takeinsocialmedia.com/wp-content/uploads/2014/05/landscape-art-painting-wallpaper-images-photos-0517193352.jpg"
);
ceiling_image = new ImageView(image);
ceiling_image.setClip(ceiling);
root.getChildren().add(ceiling_image);
【讨论】:
以上是关于JavaFX 将 ImageView 裁剪为 AnchorPane 中的椭圆的主要内容,如果未能解决你的问题,请参考以下文章