4

I have a JTable in which I want to call a function when a cell is double-clicked and call another function when the cell is triple-clicked.

When the cell is triple-clicked I do not want to call the double-click-function.

What I have right now is (mgrdAlarm is the JTable) :

mgrdAlarm.addMouseListener(new MouseAdapter()
{
  public void mouseClicked(MouseEvent e)
  {
    System.out.println("getClickCount() = " + e.getClickCount());
    if (e.getClickCount()==2)
    {
      doubleClick();
      System.out.println("Completed : doubleClick()");
    }
    if (e.getClickCount()==3)
    {
      tripleClick();
      System.out.println("Completed : tripleClick()");
    }
  }
});

When double-clicked the console shows :

getClickCount() = 1
getClickCount() = 2
Completed : doubleClick()

When triple-clicked the console shows :

getClickCount() = 1
getClickCount() = 2
Completed : doubleClick()
getClickCount() = 3
Completed : tripleClick()

When triple-clicked I want the console to show :

getClickCount() = 1
getClickCount() = 2
getClickCount() = 3
Completed : tripleClick()

So I do not want to call the function doubleClick() when the cell is triple-clicked, but I do want to call the function doubleClick() when the cell is double-clicked.

[EDIT]

As all replies suggest the solution seems to be to delay the double-click-action and wait a certain time for the triple-click.

But as discussed here that might lead to a different type of problem : The user might have set his double-click-time quite long, which might overlap with the timeout of my triple-click.

It is no real disaster if my double-click-action is executed before my triple-click-action, but it does generate some extra overhead, and especially some extra data traffic which I would like to prevent.

As the only solution so far might lead to other problems, which might actually be worse than the original problem, I will leave it as it is right now.

Community
  • 1
  • 1
Hrqls
  • 2,944
  • 4
  • 34
  • 54
  • Hmm... delay the execution? – John Dvorak Jan 16 '13 at 07:52
  • 2
    A rather interesting topic, yet not (so) simple to solve. You might want to start reading http://stackoverflow.com/questions/1067464/need-to-cancel-click-mouseup-events-when-double-click-event-detected . Single and double clicking provide the same problem. You will need to implement a bit of time tracking in your code. –  Jan 16 '13 at 07:54
  • What about implement custom EventQueue and detect one, two or triple click here? – 1ac0 Mar 24 '13 at 11:10
  • @KMaertens thanks for your answer. It seemed the way to go, but after reading another topic I think that might cause extra problems. See my edit to my post. – Hrqls Mar 25 '13 at 08:07
  • @LadislavDANKO Sorry, I am not that experienced in Java yet. What exactly do you mean, and how would I do that? – Hrqls Mar 25 '13 at 08:12

7 Answers7

4
  public class TestMouseListener implements MouseListener {    
  private boolean leftClick;
  private int clickCount;
  private boolean doubleClick;
  private boolean tripleClick;
  public void mouseClicked(MouseEvent evt) {
    if (evt.getButton()==MouseEvent.BUTTON1){
                leftClick = true; clickCount = 0;
                if(evt.getClickCount() == 2) doubleClick=true;
                if(evt.getClickCount() == 3){
                    doubleClick = false;
                    tripleClick = true;
                }
                Integer timerinterval = (Integer)Toolkit.getDefaultToolkit().getDesktopProperty("awt.multiClickInterval");

                         Timer  timer = new Timer(timerinterval, new ActionListener() {
                            public void actionPerformed(ActionEvent evt) { 

                                if(doubleClick){
                                    System.out.println("double click.");                                    
                                    clickCount++;
                                    if(clickCount == 2){
                                        doubleClick();   //your doubleClick method
                                        clickCount=0;
                                        doubleClick = false;
                                        leftClick = false;
                                    }

                                }else if (tripleClick) { 

                                    System.out.println("Triple Click.");
                                    clickCount++;
                                    if(clickCount == 3) {
                                       tripleClick();  //your tripleClick method
                                        clickCount=0;
                                        tripleClick = false;
                                        leftClick = false;
                                    }

                                } else if(leftClick) {                                      
                                    System.out.println("single click.");
                                    leftClick = false;
                                }
                            }               
                        });
                        timer.setRepeats(false);
                        timer.start();
                        if(evt.getID()==MouseEvent.MOUSE_RELEASED) timer.stop();
            }           
      }


          public static void main(String[] argv) throws Exception {

            JTextField component = new JTextField();
            component.addMouseListener(new TestMouseListener());
            JFrame f = new JFrame();

            f.add(component);
            f.setSize(300, 300);
            f.setVisible(true);

            component.addMouseListener(new TestMouseListener());
          }
   }
Anonymous
  • 152
  • 1
  • 1
  • 11
  • Thanks for your answer. It seems the same as the other answer suggest? Which has the same problem as I don't know the configured double click time of the user.. – Hrqls Nov 19 '13 at 12:46
2

The previous answers are correct: you have to account for the timing and delay recognizing it as a double click until a certain amount of time has passed. The challenge is that, as you have noticed, the user could have a very long or very short double click threshold. So you need to know what the user's setting is. This other Stack Overflow thread ( Distinguish between a single click and a double click in Java ) mentions the awt.multiClickInterval desktop property. Try using that for your threshold.

Community
  • 1
  • 1
Josh Marinacci
  • 1,715
  • 1
  • 14
  • 15
1

You can do something like that, varying delay time:

public class ClickForm extends JFrame {

final static long CLICK_FREQUENTY = 300;

static class ClickProcessor implements Runnable {

    Callable<Void> eventProcessor;

    ClickProcessor(Callable<Void> eventProcessor) {
        this.eventProcessor = eventProcessor;
    }

    @Override
    public void run() {
        try {
            Thread.sleep(CLICK_FREQUENTY);
            eventProcessor.call();
        } catch (InterruptedException e) {
            // do nothing
        } catch (Exception e) {
            // do logging
        }
    }
}

public static void main(String[] args) {
    ClickForm f = new ClickForm();
    f.setSize(400, 300);
    f.addMouseListener(new MouseAdapter() {
        Thread cp = null;
        public void mouseClicked(MouseEvent e) {
            System.out.println("getClickCount() = " + e.getClickCount() + ", e: " + e.toString());

            if (cp != null && cp.isAlive()) cp.interrupt();

            if (e.getClickCount() == 2) {
                cp = new Thread(new ClickProcessor(new Callable<Void>() {
                    @Override
                    public Void call() throws Exception {
                        System.out.println("Double click processed");
                        return null;
                    }
                }));
                cp.start();
            }
            if (e.getClickCount() == 3) {
                cp =  new Thread(new ClickProcessor(new Callable<Void>() {
                    @Override
                    public Void call() throws Exception {
                        System.out.println("Triple click processed");
                        return null;
                    }
                }));
                cp.start();
            }
        }
    });
    f.setVisible(true);
}
}
Andremoniy
  • 34,031
  • 20
  • 135
  • 241
  • thanks for your answer. It seemed the way to go, but after reading another topic I think that might cause extra problems. See my edit to my post. – Hrqls Mar 25 '13 at 08:08
0

You need to delay the execution of double click to check if its a tripple click.

Hint.

if getClickCount()==2 then put it to wait.. for say like 200ms?

Mukul Goel
  • 8,387
  • 6
  • 37
  • 77
  • thanks for your answer. It seemed the way to go, but after reading another topic I think that might cause extra problems. See my edit to my post. – Hrqls Mar 25 '13 at 08:07
0

It's exactly the same problem as detecting double-click without firing single click. You have to delay firing an event until you're sure there isn't a following click.

user207421
  • 305,947
  • 44
  • 307
  • 483
  • I had same problem [here](http://stackoverflow.com/questions/15513139/cant-filter-mouseevent-mouse-clicked-in-awt-eventqueue) – 1ac0 Mar 24 '13 at 11:12
  • @EJP thanks for your answer. It seemed the way to go, but after reading another topic I think that might cause extra problems. See my edit to my post. – Hrqls Mar 25 '13 at 08:09
0

There's a tutorial for this here

Edit: It fires click events individually though, so you would get: Single Click THEN Double Click THEN Triple Click. So you would still have to do some timing trickery.

The code is:

import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;

import javax.swing.JFrame;
import javax.swing.JTextField;

public class Main {
  public static void main(String[] argv) throws Exception {

    JTextField component = new JTextField();
    component.addMouseListener(new MyMouseListener());
    JFrame f = new JFrame();

    f.add(component);
    f.setSize(300, 300);
    f.setVisible(true);

    component.addMouseListener(new MyMouseListener());
  }
}

class MyMouseListener extends MouseAdapter {
  public void mouseClicked(MouseEvent evt) {
    if (evt.getClickCount() == 3) {
      System.out.println("triple-click");
    } else if (evt.getClickCount() == 2) {
      System.out.println("double-click");
    }
  }
}
alistair
  • 1,164
  • 10
  • 27
  • thanks for the answer ... detecting the clicks isnt that hard, detecting just a double click or a triple click (without firing the lesser-click events) is the issue ... timing trickery might work, but is trickery .. for the time being i made it so that the lesser-click events do fire, but have no drastic negative effect (other than some extra data traffic) – Hrqls Jun 04 '13 at 07:10
  • Yeah. One of the most mainstream triple click events is in text editors to select a line. They fire single, and double click events before executing the triple click code, too. – alistair Jun 04 '13 at 08:24
  • thats true ... my double click though fires an event which send some data to a device which might be heavy loaded already .. so i would want to send as little as possible (the triple click sends other data) .. but so far its working and not crashing (yet :)) – Hrqls Jun 04 '13 at 14:01
0

Here is what i have done to achieve this, this actually worked fine for me. A delay is necessary to detect the type of click. You can choose it. The following delays if a triple click can be happened within 400ms. You can decrease it to the extent till a consecutive click is not possible. If you are only worrying about the delay, then this is a highly negligible delay which must be essential to carry this out.

Here flag and t1 are global variables.

public void mouseClicked(MouseEvent e)
{
int count=e.getClickCount();
                    if(count==3)
                    {
                        flag=true;
                        System.out.println("Triple click");
                    }
                    else if(count==2)
                    {
                        try
                        {
                        t1=new Timer(1,new ActionListener(){
                            public void actionPerformed(ActionEvent ae)
                            {
                                if(!flag)
                                System.out.println("Double click");
                                flag=false;
                                t1.stop();
                            }
                        });
                        t1.setInitialDelay(400);
                        t1.start();
                        }catch(Exception ex){}
                    }
}
JavaTechnical
  • 8,846
  • 8
  • 61
  • 97