Это похоже на идеальную ситуацию для использования viewOrder
свойства Node
, добавленного в Java 9. viewOrder
контролирует, как Node
s рисуется относительно других Node
с одинаковыми Parent
без изменения порядка Node
в дочернем списке. Вот этот Javadoc:
Определяет порядок рендеринга и выбора этого узла в пределах его родительского элемента.
Это свойство используется для изменения порядка рендеринга и выбора
узел в пределах своего родителя без переупорядочения списка потомков родителя.
Например, это может быть использовано как более эффективный способ реализации
сортировка прозрачности. Для этого приложение может назначить
значение viewOrder каждого узла на вычисленное расстояние между
узел и зритель.
Родитель будет проходить по своим дочерним элементам в порядке убывания viewOrder.
Это означает, что ребенок с более низким viewOrder будет перед
ребенок с более высоким viewOrder. Если двое детей имеют одинаковые
viewOrder, родитель будет проходить их в порядке их появления
список детей родителей.
Однако viewOrder не изменяет расположение и порядок обхода фокуса
этого узла внутри его родителя. Родитель всегда пересекает своих детей
список по порядку при выполнении макета или обхода фокуса.
Вот пример использования этого свойства:
import javafx.animation.ScaleTransition;
import javafx.application.Application;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.layout.HBox;
import javafx.scene.paint.Color;
import javafx.scene.shape.Rectangle;
import javafx.stage.Stage;
import javafx.util.Duration;
import java.util.ArrayList;
public class Main extends Application {
@Override
public void start(Stage primaryStage) throws Exception {
var box = new HBox(createRectangles(Color.DARKBLUE, Color.FIREBRICK, 25));
box.setAlignment(Pos.CENTER);
box.setPadding(new Insets(50, 20, 50, 20));
primaryStage.setScene(new Scene(box));
primaryStage.show();
}
private Rectangle[] createRectangles(Color start, Color end, int count) {
var list = new ArrayList<Rectangle>(count);
for (double i = 0; i < count; i++) {
var rect = new Rectangle(30, 60, start.interpolate(end, i / count));
var scaleTrans = new ScaleTransition(Duration.millis(250), rect);
scaleTrans.setFromX(1.0);
scaleTrans.setFromY(1.0);
scaleTrans.setToX(1.2);
scaleTrans.setToY(1.2);
rect.setOnMouseEntered(e -> {
scaleTrans.stop(); // <--- doesn't seem necessary*
scaleTrans.setRate(1.0);
rect.setViewOrder(-1.0);
scaleTrans.play();
});
rect.setOnMouseExited(e -> {
scaleTrans.stop(); // <--- doesn't seem necessary*
scaleTrans.setRate(-1.0);
rect.setViewOrder(0.0);
scaleTrans.play();
});
// *the "stop()"'s don't seem to be necessary. When I commented
// them out the animation still worked. In fact, the animation
// actually seems smoother in the situation where you move the
// mouse over and then away quickly (before the zoom-in completes).
list.add(rect);
}
return list.toArray(new Rectangle[0]);
}
}
Используется Rectangle
с вместо ImageView
с, но концепция та же. Когда мышь наводит курсор на Rectangle
, она устанавливает порядок просмотра ниже, чем у других, а затем воспроизводит ScaleTransition
, чтобы увеличить его. Когда мышь выходит, она сбрасывает порядок просмотра обратно на 0
, а затем переворачивает ScaleTransition
.
Примечание: я использовал ключевое слово var
, которое было добавлено в Java 10.
А вот GIF-пример в действии:
Редактировать: Так как вы открыли CSS, я пошел и проверил, можно ли установить порядок просмотра из таблицы стилей. И кажется, что может. Глядя на Справочное руководство по CSS , для Node
определено свойство CSS с именем -fx-view-order
.