Java:检测三击而不触发双击

时间:2013-01-16 07:46:07

标签: java swing mouseevent double-click

我有一个JTable,我想在双击一个单元格时调用一个函数,并在三次单击该单元格时调用另一个函数。

当单击三次单元格时,我不想调用双击功能。

我现在所拥有的是(mgrdAlarm是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()");
    }
  }
});

双击控制台时显示:

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

三击时,控制台显示:

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

三击时,我希望控制台显示:

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

所以我不想在三次单击单元格时调用函数doubleClick(),但是我想在双击单元格时调用函数doubleClick()。

[编辑]

由于所有回复都表明解决方案似乎是延迟双击操作并等待一段时间进行三次点击。

但正如所讨论的那样here可能导致不同类型的问题: 用户可能将他的双击时间设置得相当长,这可能会与我的三次点击超时重叠。

如果我的双击操作在我的三击操作之前执行,那不是真正的灾难,但它确实会产生一些额外的开销,特别是一些我希望阻止的额外数据流量。

由于到目前为止唯一的解决办法可能会导致其他问题,这可能实际上比原来的问题更糟糕,我现在就把它留下来。

7 个答案:

答案 0 :(得分: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());
          }
   }

答案 1 :(得分:2)

之前的答案是正确的:您必须考虑时间和延迟,将其识别为双击,直到经过一定的时间。挑战在于,正如您所注意到的,用户可能具有非常长或非常短的双击阈值。所以你需要知道用户的设置是什么。此其他Stack Overflow线程(Distinguish between a single click and a double click in Java)提到awt.multiClickInterval桌面属性。尝试使用它作为你的门槛。

答案 2 :(得分:1)

你可以做类似的事情,不同的延迟时间:

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);
}
}

答案 3 :(得分:1)

有一个教程 here

编辑:它会单独触发点击事件,因此您会得到: 单击即可 双击然后 三击。所以你仍然需要做一些计时技巧。

代码是:

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");
    }
  }
}

答案 4 :(得分:0)

您需要延迟double click的执行,以检查其是tripple click

提示。

如果getClickCount()==2然后将其等待......比如说200ms

答案 5 :(得分:0)

这与检测双击而不触发单击完全相同。你必须延迟发射一个事件,直到你确定没有下一次点击。

答案 6 :(得分:0)

以下是我为实现这一目标所做的工作,这对我来说确实很好。检测点击类型需要延迟。你可以选择它。如果在400ms内发生三次点击,则会出现以下延迟。您可以将其减小到可以连续单击的程度。如果你只是担心延迟,那么这是一个非常微不足道的延迟,这对于实现这一点必不可少。

此处flagt1是全局变量。

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){}
                    }
}