Reputation: 137
I'm working on a Picture Viewer with JavaFX. My current problem is following:
Every time a new Image
is showing in the ImageViewer
(when the user clicks "Previous" or "Next") the ImageViewer
shall get recentered in its Parent
node, in this case it's a HBox
. I'm using the setTranslate
methods and it's working fine, BUT it doesn't work properly because the ImageView
is taking different positions each time when a new Image
was loaded.
I'm using this method to recenter the ImageView
:
public void adjustImageViewBounds()
{
double windowWidth = MAIN.getWindow().getScene().getWidth();
double windowHeight = MAIN.getWindow().getScene().getHeight();
double imageWidth = GUI.getImageView().getImage().getWidth();
double imageHeight = GUI.getImageView().getImage().getHeight();
boolean isFullScreen = MAIN.getWindow().isFullScreen();
GUI.getImageView().setFitWidth(windowWidth - 50 > imageWidth ? imageWidth : windowWidth - 50);
// 50 ~ 25px space on the left and right side
boolean scrollBarVisible = false;
Set<Node> nodes = GUI.getImageViewScrollPane().lookupAll(".scroll-bar");
for(Node currentNode : nodes)
{
if(currentNode instanceof ScrollBar)
if(((ScrollBar) currentNode).getOrientation() == Orientation.VERTICAL)
if(currentNode.isVisible())
scrollBarVisible = true;
}
if(!scrollBarVisible && !isFullScreen)
{
// 80 ~ GUI.getInfoBoxAndImageView().getLayoutY() -> The Y position within the window of my whole ImageView container (HBox)
// 65 ~ GUI.getLowerControl().getHeight() -> The height of the controlbar under the ImageView
double newTranslateY = (windowHeight / 2) - 80 - (VISIBLE_IMAGE_HEIGHT.divide(2).doubleValue());
GUI.getInfoBoxAndImageView().setTranslateY(newTranslateY >= 0 && (newTranslateY + 80 + VISIBLE_IMAGE_HEIGHT.doubleValue()) < (windowHeight - 65) ? newTranslateY : 0);
}
else if(scrollBarVisible)
{
GUI.getInfoBoxAndImageView().setTranslateY(0);
}
else if(isFullScreen)
{
double newTranslateY = (windowHeight / 2) - 80 - (VISIBLE_IMAGE_HEIGHT.divide(2).doubleValue());
GUI.getInfoBoxAndImageView().setTranslateY(newTranslateY >= 0 && (newTranslateY + 80 + VISIBLE_IMAGE_HEIGHT.doubleValue()) < (windowHeight - 65) ? newTranslateY : 0);
}
}
The method's working as long as I call it AFTER the Image
was loaded, but it doesn't work when I'm calling it after setting a new Image
.
Here is an example of when a new Image
is set:
public void nextClicked()
{
if(PICTURE_INDEX < picturePaths.size() - 1)
{
String path = picturePaths.get(PICTURE_INDEX + 1).toURI().toString();
GUI.getImageView().setImage(new Image(path));
adjustImageViewBounds();
PICTURE_INDEX += 1;
}
}
To solve this I've been trying to use different Listeners
:
GUI.getImageViewer().imageProperty().addListener(newImage ->
{
while(newImage.getProgress() < 1.0)
{
//Do nothing until the Image is completely loaded
}
adjustImageViewBounds();
System.out.println("End reached");
});
The end was reached actually, but the method didn't affect the ImageView
's position?!?
Also not working:
public void nextClicked()
{
if(PICTURE_INDEX < picturePaths.size() - 1)
{
String path = picturePaths.get(PICTURE_INDEX + 1).toURI().toString();
Image newImage = new Image(path);
newImage.progressProperty().addListener((obs, oldV, newV) ->
{
if(newV.doubleValue() == 1.0)
adjustImageViewBounds();
});
GUI.getImageView().setImage(newImage);
PICTURE_INDEX += 1;
}
}
Just for fun I tried this and it worked but it's not a reasonable solution of course:
GUI.getImageView().setOnMouseClicked(event -> adjustImageViewBounds());
To summarize all that confusing information:
I want my ImageView
to get recentered by the adjustImageViewBounds()
method, which works itself!
Recenter means to place my ImageView
in the mid of the Scene
, either the X
and Y
position.
Thanks in advance for your support.
Upvotes: 0
Views: 1288
Reputation: 209330
Instead of moving the ImageView
from the position that its parent determines for it, using setTranslateY(...)
, it's almost certainly better to choose and configure a parent that will position it the way you want in the first place. Both HBox
and VBox
, for example, have a setAlignment(..)
method that determines the overall alignment of the child nodes within the parent. The most "general" (i.e. flexible) predefined layout is the GridPane
, in which child nodes are positioned in a grid, and can span multiple cells in the grid. Different columns and rows in the grid can have different widths and heights, and you can configure how a child node behaves if its allocated cell(s) have more space than the node's preferred size.
Some useful links:
An overview of all the layout panes is given in the tutorial. A slightly old, but still useful, presentation on the overall layout mechanism is available on parleys.com (registration required).
Upvotes: 1