#JavaFX UI won't update

80 messages · Page 1 of 1 (latest)

hallow plover
#
public class BoardView extends GridPane {

    private final BoardPresenter presenter;
    private final SelectorView selector;

    public BoardView() {
        presenter = new BoardPresenter(this);
        displayBoard(presenter.getBoard());
        selector = new SelectorView(new SelectorPresenter());
        presenter.selectionProperty().addListener((_, _, newValue) -> {
            getChildren().remove(selector);
            if (newValue == null)
                return;
            add(selector, newValue.x(), newValue.y());
        });
    }

The line getChildren().remove get's executed on the application thread and does remove the child.
But the UI doesn't update/repaint because when I resize my window the selector disappears.
When I run my app with debug the ui properly updates but when I don't run it with debug it doesn't

muted haloBOT
#

This post has been reserved for your question.

Hey @hallow plover! Please use /close or the Close Post button above when your problem is solved. Please remember to follow the help guidelines. This post will be automatically marked as dormant after 300 minutes of inactivity.

TIP: Narrow down your issue to simple and precise questions to maximize the chance that others will reply in here.

unborn barn
#

i have no idea

muted haloBOT
#

💤 Post marked as dormant

This post has been inactive for over 300 minutes, thus, it has been archived.
If your question was not answered yet, feel free to re-open this post or create a new one.
In case your post is not getting any attention, you can try to use /help ping.
Warning: abusing this will result in moderative actions taken against you.

hasty pumice
#

Why should it update when resizing?

hallow plover
#

It should update when i call remove

#

But it doesn't

#

It does when you manually update the ui with something like resizing the window

hasty pumice
#

Did you check whether remove is called?

#

Does the size actually change?

hallow plover
#

Yes the size changes

#

And yes remove gets called

#

It does only seem to happen if the property changes it's value to null

#

It's a javafx objectproperty btw

hasty pumice
#

Can you try replacing the element by an "empty" element?

#

instead of just removing it

hallow plover
#

Not at the moment but I will tomorrow

#

That would be strange if that would work though

muted haloBOT
#

💤 Post marked as dormant

This post has been inactive for over 300 minutes, thus, it has been archived.
If your question was not answered yet, feel free to re-open this post or create a new one.
In case your post is not getting any attention, you can try to use /help ping.
Warning: abusing this will result in moderative actions taken against you.

hallow plover
#
public class BoardView extends GridPane {

    private final BoardPresenter presenter;
    private final SelectorView selector;

    public BoardView() {
        presenter = new BoardPresenter(this);
        selector = new SelectorView(new SelectorPresenter());

        displayBoard(presenter.getBoard());
        presenter.selectionProperty().addListener((_, oldValue, newValue) -> {
            getChildren().remove(selector);
            if (oldValue != null)
                add(new ImageView(), oldValue.x(), oldValue.y());

            if (newValue != null) {
                add(selector, newValue.x(), newValue.y());
            }
        });
    }
#

this works

#

putting an empty image at the old place

#

but that's a hacky solution

hasty pumice
#

like maybe it doesn't like the remove()

hallow plover
#

removeIf doesn't work either

#

but I found layout()

#

and layoutChildren()

#

but they also both don't work

#

maybe it has something to do with that in the same grid cell there are multiple imageViews

#

I have an image of a gem and the selector in the same cell

#

because when I remove all images from the same cell the selector does disappear

#

but when I only remove the selector the selector does not appear

#

The SelectorView also isn't a normal ImageView

public class SelectorView extends ImageView {

    private final SpriteAnimation animation;

    public SelectorView(SelectorPresenter presenter) {
        super(new Image(ResourceManager.getResource(presenter.getImagePath())));
        animation = new SpriteAnimation(
                this,
                Duration.millis(1000),
                presenter.getFrameCount(),
                presenter.getColumnCount(),
                presenter.getOffsetX(),
                presenter.getOffsetY(),
                presenter.getSpriteWidth(),
                presenter.getSpriteHeight()
        );
        animation.setCycleCount(Animation.INDEFINITE);
        animation.play();
    }
}
#
public class BoardView extends GridPane {

    private final BoardPresenter presenter;
    private final SelectorView selector;

    public BoardView() {
        presenter = new BoardPresenter(this);
        selector = new SelectorView(new SelectorPresenter());

        displayBoard(presenter.getBoard());
        presenter.selectionProperty().addListener((_, oldValue, newValue) -> {

            selector.getAnimation().stop();
            getChildren().remove(selector);
            layout();

            if (newValue != null) {
                add(selector, newValue.x(), newValue.y());
                selector.getAnimation().play();
            }
        });
    }
hasty pumice
#

Do you have a custom add method?

hallow plover
#

no

hasty pumice
#

Can you show a minimal reproducer?

#

instead of replacing it with an empty ImageView, you could try replacing it with an empty Node or whatever

hallow plover
#

I can't seem to reproduce it

#
package nowipi.bejeweled;

import javafx.application.Application;
import javafx.beans.property.ObjectProperty;
import javafx.beans.property.SimpleObjectProperty;
import javafx.scene.Scene;
import javafx.scene.image.ImageView;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.GridPane;
import javafx.stage.Stage;
import nowipi.bejeweled.domain.Vector2;

public class JavaFXProblem extends Application {

    private static final int WIDTH = 8;
    private static final int HEIGHT = 8;

    private final ObjectProperty<Vector2> selection = new SimpleObjectProperty<>();
    private final ImageView selector;

    public JavaFXProblem() {
        selector = new ImageView("https://d2bzx2vuetkzse.cloudfront.net/unshoppable_producs/a948fba6-5a77-4256-bc0d-65429a880128.png");
        selector.setFitWidth(64);
        selector.setFitHeight(64);
    }

    @Override
    public void start(Stage primaryStage) {
        GridPane grid = new GridPane();
        fillGrid(grid);
        selectionProperty().addListener((_, _, newValue) -> {
            System.out.println(newValue);
            grid.getChildren().remove(selector);
            grid.layout();

            if (newValue != null) {
                grid.add(selector, newValue.x(), newValue.y());
            }
        });
        primaryStage.setScene(new Scene(grid));
        primaryStage.show();
    }

    private void fillGrid(GridPane grid) {
        for (int y = 0; y < HEIGHT; y++) {
            for (int x = 0; x < WIDTH; x++) {
                ImageView imageView = new ImageView("https://cdn-icons-png.flaticon.com/512/226/226777.png");
                imageView.setFitWidth(64);
                imageView.setFitHeight(64);

                final int finalX = x;
                final int finalY = y;
                imageView.addEventHandler(MouseEvent.MOUSE_CLICKED, _ -> click(finalX, finalY));

                grid.add(imageView, x, y);
            }
        }
    }
#
private void click(int gridX, int gridY) {
        if (getSelection() == null) {
            setSelection(gridX, gridY);
        } else {
            if (isAdjacent(getSelection().x(), getSelection().y(), gridX, gridY)) {
                selection.set(null);
            } else {
                setSelection(gridX, gridY);
            }
        }
    }

    private boolean isAdjacent(int aX, int aY, int bX, int bY) {
        int dx = Math.abs(aX - bX);
        int dy = Math.abs(aY - bY);
        return (dx == 1 && dy == 0) || (dx == 0 && dy == 1);
    }

    public void setSelection(int x, int y) {
        selection.set(new Vector2(x, y));
    }

    public Vector2 getSelection() {
        return selection.get();
    }

    public ObjectProperty<Vector2> selectionProperty() {
        return selection;
    }

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

This works fine although clicks don't always register

#

Than it has to be something that has to do with it having animations

hasty pumice
#

ig maybe stuff doesn't disappear during animations

#

but I can't do much except guessing if I can't reproduce it

hallow plover
#

I am using Transition

hallow plover
#

it's definitely the remove call

#

but I think it's a JavaFX bug

#

the grid isn't redrawing because I have another image under it

hasty pumice
#

What do you mean with having another image under it?

#

What happens if you remove it and add another element at a different position?

hallow plover
#

The grid is filled with imageviews

hasty pumice
hallow plover
hasty pumice
hallow plover
#

below

#

oh no

#

soryy

#

behind

hasty pumice
#

Does it still happen without the image behind?

#

btw you could try not removing any ImageViews at all but just do yourImageView.setImage(yourNewImage)

hallow plover
#
public class BoardView extends GridPane {

    private final BoardPresenter presenter;
    private final GemView[][] gems;

    public BoardView() {
        presenter = new BoardPresenter(this);

        presenter.selectionProperty().addListener((_, oldValue, newValue) -> {
            if (oldValue != null) {
                GemView view = getGem(oldValue.x(), oldValue.y());
                view.deselect();
            }

            if (newValue != null) {
                GemView view = getGem(newValue.x(), newValue.y());
                view.select();
            }
        });

        gems = presenter.getGems();

        for (int y = 0; y < gems.length; y++) {
            for (int x = 0; x < gems[y].length; x++) {
                GemView view = getGem(x, y);

                final int gemX = x;
                final int gemY = y;
                view.addEventHandler(MouseEvent.MOUSE_CLICKED, _ -> presenter.click(gemX, gemY));

                add(view, x, y);
            }
        }
    }

    public GemView getGem(int x, int y) {
        return gems[y][x];
    }
}
#

fixed it

#
public class GemView extends StackPane {


    private final SpriteAnimation selectAnimation;
    private final ImageView gem;
    private final SelectorView selector;

    public GemView(GemPresenter presenter) {
        gem = new ImageView(new Image(ResourceManager.getResource(presenter.getImagePath())));
        selector = new SelectorView();
        getChildren().add(gem);
        getChildren().add(selector);

        selectAnimation = new SpriteAnimation(
                gem,
                Duration.millis(1000),
                presenter.getFrameCount(),
                presenter.getColumnCount(),
                presenter.getOffsetX(),
                presenter.getOffsetY(),
                presenter.getSpriteWidth(),
                presenter.getSpriteHeight()
        );
        selectAnimation.setCycleCount(Animation.INDEFINITE);
    }

    public void select() {
        selectAnimation.play();
        selector.select();
    }

    public void deselect() {
        selectAnimation.stop();
        selectAnimation.interpolate(0);
        selector.deselect();
    }
}
#
public class SelectorView extends ImageView {

    private final Image image;
    private final SpriteAnimation animation;

    public SelectorView() {
        this(new SelectorPresenter());
    }

    private SelectorView(SelectorPresenter presenter) {
        image = new Image(ResourceManager.getResource(presenter.getImagePath()));
        animation = new SpriteAnimation(
                this,
                Duration.millis(1000),
                presenter.getFrameCount(),
                presenter.getColumnCount(),
                presenter.getOffsetX(),
                presenter.getOffsetY(),
                presenter.getSpriteWidth(),
                presenter.getSpriteHeight()
        );
        animation.setCycleCount(Animation.INDEFINITE);
    }

    public void select() {
        setImage(image);
        animation.play();
    }

    public void deselect() {
        animation.stop();
        setImage(null);
    }
}
#

I treated ImageView's like they were images and that's not what they are for

#

Now I treat them as things that display an image and it works

#

I still think I encountered a JavaFX bug though

#

but this is a way cleaner solution

hasty pumice
#

though if you show me before, I could maybe check about it actually being some intentional thing

#

if you don't want to: you don't have to

#

also it could be fixed by updating JavaFX

muted haloBOT
#

💤 Post marked as dormant

This post has been inactive for over 300 minutes, thus, it has been archived.
If your question was not answered yet, feel free to re-open this post or create a new one.
In case your post is not getting any attention, you can try to use /help ping.
Warning: abusing this will result in moderative actions taken against you.