-1

I have an event handler for checking if the hbox was pressed. This event handler uses a parallel thread to check if the button was pressed longer than a set ammount of time. If it is, it sets editMode true. This worked for me but suddenly it started to randomly enter the method when it coudn't. It shoudn't be possible for the loop to enter the if statement for checking if more than 800ms have passed, more than one time, because it sets edit mode to true which should break the loop on the next iteration. But I have noticed that it does eneter that if statement again. It does so randomly and a random ammount of times, sometimes two and sometimes even 5 or 6 times. this is the code

hBox.addEventHandler(MouseEvent.MOUSE_PRESSED, new EventHandler<MouseEvent>() {
            @Override
            public void handle(javafx.scene.input.MouseEvent e) {
                mousePressed = true;
                pillReminder.setSelected(true);

                double pressedTime = System.currentTimeMillis();
                hBox.setBackground(new Background(new BackgroundFill(Color.CYAN, CornerRadii.EMPTY, Insets.EMPTY)));

                new Thread() {
                    @Override
                    public void run() {
                        try {
                            Thread.sleep(800);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }

                        if (mousePressed) {
                            editMode = true;

                            //cannot thread javafx so need to use platform
                            Platform.runLater(new Runnable() {
                                @Override
                                public void run() {
                                    handleEditMode();
                                }
                            });
                        }
                    }
                }.start();
            }
        });

        hBox.addEventHandler(MouseEvent.MOUSE_RELEASED, new EventHandler<MouseEvent>() {
            @Override
            public void handle(MouseEvent mouseEvent) {
                if (!editMode) {
                    mousePressed = false;
                    hBox.setBackground(new Background(new BackgroundFill(Color.LIGHTCYAN, CornerRadii.EMPTY, Insets.EMPTY)));
                    if (hBox.getBoundsInLocal().contains(new Point2D(mouseEvent.getX(), mouseEvent.getY())))
                        handleReminderHubReleased(pillReminder);
                }
            }
        });

This is the handleEditMode method and its sub methods:

private void handleEditMode() {
    home.getAppManager().getAppBar().getActionItems().add(MaterialDesignIcon.DELETE.button(e ->
            handleRemove()));

    home.getAppManager().getAppBar().getActionItems().add(MaterialDesignIcon.CANCEL.button(e ->
            handleCancelEdit()));
}

private void handleRemove() {
    ListIterator<PillHub> iter = HubData.getInstance().getHubs().listIterator();

    while (iter.hasNext()) {
        if(iter.next().isSelected()) {
            iter.previous();
            iter.remove();
        }
    }

    handleCancelEdit();

    //redo the hub list in home
    hubVBox.getChildren().clear();
    initialize();
}

private void handleCancelEdit() {
    editMode = false;

    for(PillHub ph : HubData.getInstance().getHubs()) {
        if(ph.isSelected()) {
            ph.gethBox().setBackground(new Background(new BackgroundFill(Color.LIGHTCYAN, CornerRadii.EMPTY, Insets.EMPTY)));
            ph.setSelected(false);
        }
    }

    home.getAppManager().getAppBar().getActionItems().clear();
}
  • I think you should schedule a task to run in 800ms that checks for conditions. Right now you're using shared data. If mouse pressed happens once, it starts the loop. Then if mouse pressed happens again, it changes the criteria for the loop which means the condition for edit mode might be satisfied, even though it wasn't. Is your HBox accumulating more and more handlers? You never remove them, but you add them in a while loop. – matt Feb 10 '23 at 16:06
  • Maybe you should change your question, to what you're trying to do. How can I have a mouse event trigger an action if the mouse is held down, within the component long enough. – matt Feb 10 '23 at 16:07
  • 1
    Maybe [this](https://stackoverflow.com/questions/27162374/javafx-2-user-idle-detection/27163223#27163223) can help? Create a minimal, complete, working example that demos the current issue. – SedJ601 Feb 10 '23 at 16:10
  • 1
    [mcve] please .. please read that help page to understand what's needed :) – kleopatra Feb 10 '23 at 16:12
  • Do you want edit mode to start while the mouse button is still pressed down? Or is it OK to enter it when the mouse button is released after at least 800 milliseconds? If the latter, then just set a time stamp when the mouse button is pressed, and check it when the mouse button is released. No need for looping, tasks and potential concurrency issues. – DaveB Feb 10 '23 at 16:13
  • @matt : All the issues that you have seen here are adressed in other parts of the code (a handler for mouse release sets mouse pressed to false and there is a method for deleting all the HBoxes) – MilckShake Beans Feb 10 '23 at 16:36
  • @DaveB : I do want to enter edit mode when the mouse has been pressed for longer than 800ms, and I don't want it to check this only when the mouse is released because it would make the UI less clear. There is probably a concurrency issue here. – MilckShake Beans Feb 10 '23 at 16:38
  • I'll try to make a a minimal complete working example if I could recreate the issue again in different code. The issue arose when I made a change to the handleEdit method to be able to remove all selected items from the list. Before this update I would send the specific pillHub that was pressed and only deleting it when handleRemoved was called. Now when updating whether a pillHub is selected it iterating through the list to remove selected items it broke, it is probably something to do with the loop if I would guess, - – MilckShake Beans Feb 10 '23 at 16:49
  • You really didn't address any of the issues I raised. Your using some mousePressed field it is being modified any number of threads along with any time an action is activated. You could reduce this down to a button. "How do I get an action to happen after the button is pressed for 800ms?" Minimal reproducible example. Your whole busy loop can be replaced with a ScheduledExecutor running the task in 800ms. – matt Feb 10 '23 at 16:49
  • - this is weird because the loop is called only when the handleRemove. This method isn't called when the bug occures. – MilckShake Beans Feb 10 '23 at 16:53
  • @matt : I updated it and removed the unnecessary loop but it still has the same issue. It enters the the handleRemove method multiple times. – MilckShake Beans Feb 10 '23 at 16:59
  • There is still a loop. " while (true) {" You've said what you need to do, make a minimal example. Either you'll find the bug in the process or somebody might be able to help. – matt Feb 10 '23 at 17:01
  • sorry, I have updated it in my code but not here. Will do. Trying to repreduce this bug on a javafx application. – MilckShake Beans Feb 10 '23 at 17:04
  • Don't use the loop. Create a global variable, `lastClick`, to hold the click time. Update it with the current time when the mouse button is clicked. Then start a `PauseTransition` for 800ms. In its `onFinished` action, check to see if `lastClick` is still equal to the same value. When the mouse button is released set `lastClick` to zero or `Null`. – DaveB Feb 10 '23 at 17:41

1 Answers1

0

I found out the issue. It isn't possible to solve with the info you had (very very sorry for that). Every time I opened the view that had this event handler it attached it again. The result is that every hbox got addtional event handlers every time I entered this window. Sorry again for this. I would be glad if a mod closed this.

  • You can remove your own question, unless perhaps the given answers block the deletion. In that case you can accept your own answer so that it won't show up as open. – Dávid Laczkó Feb 11 '23 at 11:57