У меня есть изменяемый размер ImageView
, и некоторые части изображения должны быть кликабельными.Моя идея состояла в том, чтобы создать GridPane
, который будет действовать как наложение и расположить внутри него несколько прозрачных кнопок, чтобы при нажатии пользователем какой-либо части изображения он фактически вызывал скрытую кнопку над изображением:
<!-- parent that resizes from time to time -->
<StackPane>
<StackPane>
<!-- background image, preserves ration -->
<ImageView/>
<!-- overlay with transparent buttons -->
<!-- should be positionion exactly the same as Image inside ImageView -->
<GridPane>
<!- buttons here, columns == rows -->
</GridPane>
</StackPane>
</StackPane>
Код выглядит следующим образом:
StackPane stackPane_wrapper = new StackPane();
stackPane_wrapper.setAlignment(Pos.CENTER);
//menu wheel
WrappedImageView imageView_wheel = new WrappedImageView();
imageView_wheel.setImage(new Image("images/menu-wheel.png"));
imageView_wheel.setPreserveRatio(true);
stackPane_wrapper.getChildren().add(imageView_wheel);
GridPane gridPane_overlay = new GridPane();
stackPane_wrapper.getChildren().add(gridPane_overlay);
int size = 20;
for (int i = 0; i < size; ++i)
{
ColumnConstraints columnConstraints = new ColumnConstraints();
columnConstraints.setPercentWidth(100.0d / size);
gridPane_overlay.getColumnConstraints().add(columnConstraints);
RowConstraints rowConstraints = new RowConstraints();
rowConstraints.setPercentHeight(100.0d / size);
gridPane_overlay.getRowConstraints().add(rowConstraints);
}
Button button = new Button();
button.setText("test");
//... set style to make this button transparent
gridPane_overlay.add(button, 3, 5, 2, 4);
Моя проблема в том, что я не могу поместить gridPane_overlay
в то же положение, что и Image
внутри ImageView
.Image
внутри imageView_wheel
продолжает изменять размеры и менять свою позицию, что вполне нормально, но я не знаю, как назначить его размер и позицию для gridPane_overlay
.
Я пытаюсь добавить слушателей к различным xСвойства / y и width / height позволили достичь некоторых результатов, но он прекратил работать, когда сцена была развернута до максимума и сохранила совершенно неправильные координаты.
Обновление:
Похоже, getParentInParent.getWidth()
и getParentInParent.getHeight()
возвращают правильный размер Image
внутри WrappedImageView
, теперь мне нужно определить его положение и назначить размер и позицию для сетки.
Обновление 2:
На основании комментариев я принял следующее решение:
/**
*
* @param bounds bounds of image - result of {@link WrappedImageView#localToScene(Bounds)} from {@link WrappedImageView#getBoundsInLocal()}
* @param x click X - {@link MouseEvent#getSceneX()} minus {@link Bounds#getMinX()}
* @param y click Y - {@link MouseEvent#getSceneY()} minus {@link Bounds#getMinY()}
* @return
*/
private int determineClick(Bounds bounds, double x, double y)
{
double centerX = bounds.getWidth() / 2;
double centerY = bounds.getHeight() / 2;
double angle = Math.toDegrees(Math.atan2(x - centerX, y - centerY));
Point2D center = new Point2D(centerX, centerY);
Point2D click = new Point2D(x, y);
double distance = center.distance(click);
double diameter = centerX;
boolean isInner = distance < diameter * 0.6;
//-90 -> -135
if (angle <= -90 && angle > -135)
{
if (isInner)
{
return 10;
}
return 0;
}
//-135 -> -180/180
if (angle <= -135 && angle > -180)
{
if (isInner)
{
return 11;
}
return 1;
}
//-180/180 -> 135
if (angle <= 180 && angle > 135)
{
if (isInner)
{
return 12;
}
return 2;
}
//135 -> 90
if (angle <= 135 && angle > 90)
{
if (isInner)
{
return 13;
}
return 3;
}
//90 -> 45
if (angle <= 90 && angle > 45)
{
if (isInner)
{
return 14;
}
return 4;
}
//45 -> -0/0
if (angle <= 45 && angle > 0)
{
if (isInner)
{
return 15;
}
return 5;
}
//-0/0 -> -45
if (angle <= 0 && angle > -45)
{
if (isInner)
{
return 16;
}
return 6;
}
//-45 -> -90
if (angle <= -45 && angle > -90)
{
if (isInner)
{
return 17;
}
return 7;
}
throw new RuntimeException("Unable to determine point coordinates");
}