Подтвердить что ты не робот

Радиус рамки и тени на ImageView

Я хочу применить радиус границы и тень в JavaFX.

В CSS3 это будет:

box-shadow: rgba(0,0,0,0.8) 0 0 10px;
border-radius: 3px;

Теперь я хочу это в JavaFX, но даже пограничный радиус не работает в JavaFX Scene Builder. Вот скриншот моей проблемы:

JavaFX Screenshot
(источник: rapid-img.de)

На скриншоте видно, что я использую:

-fx-border-radius: 10 10 10 10;
-fx-background-radius: 10 10 10 10;
4b9b3361

Ответ 1

Используйте следующую css для получения тени:

-fx-effect: dropshadow(three-pass-box, rgba(0,0,0,0.8), 10, 0, 0, 0);

Подробнее см. Справочное руководство по JavaFX CSS.

Чтобы получить границу в дополнение к тени, поместите свой ImageView, содержащий ваше изображение, в StackPane. И примените эффект css выше к StackPane, в дополнение к фону и дополнению на StackPane.

Например, css ниже применяется к StackPane, содержащему ваш ImageView, обеспечит красную рамку вокруг вашего изображения:

-fx-padding: 10;
-fx-background-color: firebrick;

Если вы хотите, чтобы фон определял вашу границу, изогнутую по краям, используйте:

-fx-background-radius: 5;

Это даст вам изображение, как показано ниже, где ваше изображение заключено в затененную рамку:

batmanlost

Если вы хотите повернуть вокруг самого изображения, это немного сложнее. Вам необходимо применить код:

  • Закрепите изображение на закругленном прямоугольнике.
  • Снимок обрезанного изображения.
  • Сохраните изображение моментального снимка в ImageView.
  • Удалить клип из ImageView.
  • Примените эффект тени к ImageView.

Затем вы можете получить что-то вроде ниже:

whereisbatman

Некоторый код для этого "BatmanLost.java":

import javafx.application.Application;
import javafx.fxml.*;
import javafx.scene.*;
import javafx.scene.effect.DropShadow;
import javafx.scene.image.*;
import javafx.scene.layout.Pane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Rectangle;
import javafx.stage.Stage;

import java.io.IOException;

public class BatmanLost extends Application {

    class WingClipper {
        @FXML
        private ImageView imageView;

        @FXML
        public void initialize() {
            // set a clip to apply rounded border to the original image.
            Rectangle clip = new Rectangle(
                imageView.getFitWidth(), imageView.getFitHeight()
            );
            clip.setArcWidth(20);
            clip.setArcHeight(20);
            imageView.setClip(clip);

            // snapshot the rounded image.
            SnapshotParameters parameters = new SnapshotParameters();
            parameters.setFill(Color.TRANSPARENT);
            WritableImage image = imageView.snapshot(parameters, null);

            // remove the rounding clip so that our effect can show through.
            imageView.setClip(null);

            // apply a shadow effect.
            imageView.setEffect(new DropShadow(20, Color.BLACK));

            // store the rounded image in the imageView.
            imageView.setImage(image);
        }
    }

    public static void main(String[] args) {
        launch(args);
    }

    @Override
    public void start(Stage stage) throws IOException {
        FXMLLoader loader = new FXMLLoader(
            getClass().getResource(
                "batmanlostinthemix.fxml"
            )
        );
        loader.setController(new WingClipper());

        Pane batman = loader.load();

        stage.setTitle("Where Batman?");
        stage.setScene(new Scene(batman));
        stage.show();
    }
}

С некоторыми FXML "batmanlostinthemix.fxml":

<?xml version="1.0" encoding="UTF-8"?>

<?import javafx.scene.image.Image?>
<?import javafx.scene.image.ImageView?>
<?import javafx.scene.layout.AnchorPane?>

<AnchorPane id="AnchorPane" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="313.0" prefWidth="477.0" style="-fx-background-color: azure;" xmlns:fx="http://javafx.com/fxml/1" xmlns="http://javafx.com/javafx/2.2">
  <children>
    <ImageView fx:id="imageView" layoutX="29.0" layoutY="44.0" fitHeight="224.0" fitWidth="400.0" pickOnBounds="true" preserveRatio="true">
      <image>
        <Image url="http://collider.com/wp-content/uploads/lego-batman-movie-dc-super-heroes-unite-1.jpg" />
      </image>
    </ImageView>
  </children>
</AnchorPane>

Ответ 2

Если вы используете ответ, предоставленный jewelsea, убедитесь, что сначала проверьте, поддерживается ли обрезка:

Platform.isSupported(ConditionalFeature.SHAPE_CLIP)

Я стараюсь избегать условных функций, если я не буду использовать их. В моем случае я хотел сделать фотографию круглой. Таким образом, альтернативой будет использование Circle вместо ImageView:

Circle circle = new Circle(14);
ImagePattern pattern = new ImagePattern(myImage);
circle.setFill(pattern);

Круг может быть расширен для использования тени, если поддерживается:

if (Platform.isSupported(ConditionalFeature.EFFECT)) {
    circle.setEffect(new DropShadow(8, Color.rgb(0, 0, 0, 0.8)));
}

Ответ 3

Спасибо Мартину за указание на ImagePattern

enter image description here

Rectangle rectangle = new Rectangle(0, 0, 280, 180);
rectangle.setArcWidth(30.0);   // Corner radius
rectangle.setArcHeight(30.0);

ImagePattern pattern = new ImagePattern(
    new Image("file:images/mustang-gt.jpg", 280, 180, false, false) // Resizing
);

rectangle.setFill(pattern);
rectangle.setEffect(new DropShadow(20, Color.BLACK));  // Shadow

Обратите внимание, что здесь я изменяю размер изображения, чтобы соответствовать размеру прямоугольника во время его загрузки, чтобы обеспечить плавность.