0

JavaFX 2.2 - JDK 1.8.0_121

I have a TextArea inside a rectangle which also happens to have a mouse listener. The problem is that when I click on the TextArea it consumes the event and the rectangle doesn't get the click.

Consider the following code for example:

Group g = new Group();

Rectangle rect = new Rectangle(100,100);

TextArea textArea = new TextArea("Test");
textArea.setTranslateX(rect.getX());
textArea.setTranslateY(rect.getY());
textArea.setMinWidth(rect.getWidth());
textArea.setMinHeight(rect.getHeight());

//Calling a method to add an onMouseClickedProperty() mouse listener to the rectangle
addMouseListener(rect) 

g.getChildren().addAll(rect, textArea);

In the above case the TextArea takes as much space as the rectangle so when I click on it the onMouseClickedProperty() event gets consumed by the TextArea.

Is there a way to "disable" or "remove" the onMouseClickedProperty() from the TextArea and instead have it fired when a double click occurs? In hopes that the single mouse click will be consumed by the rectangle instead.

Thanks.

EDIT:

I found a solution that works, it's not perfect but it's much more appropriate than what it was discussed in the comments.

Since you can't prevent the TextArea from consuming the MOUSED_PRESSED event the only way to process an event before TextArea areas does is using event filters.

So using the example code from above where i call the method addMouseListener(rect) instead of using just a mouse listener I'm adding an event filter, and instead of adding that to the rectangular shape I add it to the group.

private void addMouseLisenter(Group group){

group.addEventFilter(MouseEvent.MOUSE_PRESSED,
                new EventHandler<MouseEvent>() {
                    public void handle(MouseEvent event) {
                        //Code here    
                    }
                 });
    }

This way both the group and the TextArea get the mouse click.

Note: If you want only the group to get the mouse click you can add event.consume().

I hope that helps someone in the future looking for something similar.

Nick
  • 368
  • 1
  • 7
  • 16

2 Answers2

1

I am pretty sure you cannot get away from having to have the MouseListener unfortunately as that is primary class for all mouse events if you wanted the text area to react at all to mouse it has to have the listener.

as far as detecting double clicks there is another thread that contains the answer that you are seeking answered by Uluk Biy.

there is another answer on there proposed by mipa that might answer your question on detection of difference between single and double click however if the Nodes overlap each other.

EDIT

perhaps in this case it might be worth modifying mipa's answer, try adding this to your code (in applicable areas)

Integer clickCount = 0;

ScheduledThreadPoolExecutor executor = new ScheduledThreadPoolExecutor(1);
ScheduledFuture<?> scheduledFuture;

root.setOnMouseClicked(new EventHandler<MouseEvent>() {
        @Override
        public void handle(MouseEvent e) {
            if (e.getButton().equals(MouseButton.PRIMARY) && clickCount < 1) {
                    scheduledFuture = executor.schedule(() -> clickAction(), 500, TimeUnit.MILLISECONDS);    
            }
            clickCount += 1;
        }
});

private void clickAction() {
    if (clickCount == 1) {
       //actions for single click
       clickCount = 0;
    } else if (clickCount > 1) {
       //action for multiple clicks
       clickCount = 0;
    }
}
Community
  • 1
  • 1
TravisF
  • 459
  • 6
  • 13
  • Found the above answer before and I tried it in hopes that it would override the single click and have the event fire only on double click but sadly single click didn't is still firing. I thought of a workaround, haven't tried it yet, that I'm not really keen on. I was thinking of having the TextArea visibility set to false and on top of it have a label when someone double clicks on the label the label would go invisible and the textarea would appear. Once the focus is lost the text from the textarea would be transfered back to the label and set the label to visible, any thoughts on that? – Nick Apr 25 '17 at 23:07
  • even with mipa's answer? this creates a timer that will wait for a second click before it assumes that it single only? – TravisF Apr 25 '17 at 23:08
  • Oh sorry, completely missed that part of mipas answer, I'm having a look now and I'll let you know. Thanks. – Nick Apr 25 '17 at 23:10
  • It didn't work, in a single click his code will work and print the message in 500ms but the TextArea gains the focus instantly, doesn't wait for the 500ms to be over. – Nick Apr 25 '17 at 23:23
  • A fix for your edit, you have to instantiate executor, but even then the same thing happens as with mipa's answer. After a 500ms delay the code in the single click will run but the TextArea gains focus instantly. It feels like there is some other event that handles that for the TextArea. I even tried onMouseClickedProperty() instead of the onMouseClicked() but same results. – Nick Apr 25 '17 at 23:49
  • can you put an invisible rectangle overtop of the text area and put the mouse event on that rectangle and in the double click action then make the `rectangle.visible(false);` – TravisF Apr 26 '17 at 00:01
  • Yes that works, I could do that and have it set visible as soon as TextArea loses focus and then set the TextArea to disabled which doesn't make it disappear but it becomes grey. I guess that's a better solution than the label one, won't require "transferring" the text from one to another. Include that as possible solution in your answer and I'll wait a day. If nothing else comes up I'll choose it as best solution. – Nick Apr 26 '17 at 00:12
  • cool, don't forget to do `textarea.requestFocus();` on the double click (so they don't have to click for a third time on the textarea.) – TravisF Apr 26 '17 at 00:19
0

I found a much more appropriate solution than what was discussed, check EDIT in my question.

Nick
  • 368
  • 1
  • 7
  • 16