【问题标题】:Java : detect triple-click without firing double-clickJava:检测三击而不触发双击
【发布时间】:2012-12-30 11:35:19
【问题描述】:

我有一个 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 所讨论的那样,这可能会导致不同类型的问题: 用户可能将他的双击时间设置得很长,这可能与我的三次单击超时重叠。

如果我的双击操作在我的三次单击操作之前执行,这并不是真正的灾难,但它确实会产生一些额外的开销,尤其是一些我想阻止的额外数据流量。

由于目前唯一的解决方案可能会导致其他问题,这实际上可能比原来的问题更糟糕,所以我将保持原样。

【问题讨论】:

  • 嗯...延迟执行?
  • 一个相当有趣的话题,但解决起来并不(那么)简单。您可能想开始阅读 stackoverflow.com/questions/1067464/… 。单击和双击提供了相同的问题。您需要在代码中实现一些时间跟踪。
  • 如何实现自定义 EventQueue 并在此处检测一次、两次或三次点击?
  • @KMaertens 感谢您的回答。这似乎是要走的路,但在阅读了另一个主题后,我认为这可能会导致额外的问题。查看我对帖子的编辑。
  • @LadislavDANKO 抱歉,我还没有 Java 方面的经验。你到底是什么意思,我该怎么做?

标签: java swing mouseevent double-click


【解决方案1】:
  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());
          }
   }

【讨论】:

  • 感谢您的回答。似乎与其他答案建议的相同?与我不知道用户配置的双击时间相同的问题..
【解决方案2】:

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

【讨论】:

    【解决方案3】:

    你可以做类似的事情,改变延迟时间:

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

    【讨论】:

    • 感谢您的回答。这似乎是要走的路,但在阅读了另一个主题后,我认为这可能会导致额外的问题。查看我对帖子的编辑。
    【解决方案4】:

    您需要延迟double click 的执行以检查它是否为tripple click

    提示。

    如果getClickCount()==2 然后让它等待.. 说像200ms

    【讨论】:

    • 感谢您的回答。这似乎是要走的路,但在阅读了另一个主题后,我认为这可能会导致额外的问题。查看我对帖子的编辑。
    【解决方案5】:

    这与检测双击而不触发单击完全相同的问题。您必须延迟触发事件,直到您确定没有后续点击。

    【讨论】:

    • 我有同样的问题here
    • @EJP 感谢您的回答。这似乎是要走的路,但在阅读了另一个主题后,我认为这可能会导致额外的问题。查看我对帖子的编辑。
    【解决方案6】:

    有一个教程 here

    编辑:它会单独触发点击事件,所以你会得到: 单击 THEN 双击 THEN 三击。所以你仍然需要做一些时间技巧。

    代码是:

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

    【讨论】:

    • 感谢您的回答...检测点击并不难,仅检测双击或三次点击(不触发较少点击事件)是问题...计时技巧可能会起作用,但是很狡猾..暂时我做到了,以便较小的点击事件确实触发,但没有严重的负面影响(除了一些额外的数据流量)
    • 是的。最主流的三次单击事件之一是在文本编辑器中选择一行。它们也会在执行三次单击代码之前触发单击和双击事件。
    • 那是真的......我的双击虽然触发了一个事件,该事件将一些数据发送到可能已经很重的设备..所以我想尽可能少地发送(三次点击发送其他数据)..但到目前为止它的工作并且没有崩溃(还:))
    【解决方案7】:

    这是我为实现这一目标所做的工作,这对我来说实际上效果很好。检测点击类型需要延迟。你可以选择它。如果可以在 400 毫秒内发生三次单击,则会出现以下延迟。您可以将其减小到无法连续单击的程度。如果您只是担心延迟,那么这是一个可以忽略不计的延迟,它必须是执行此操作所必需的。

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-11-12
      • 2015-03-01
      • 2011-03-07
      相关资源
      最近更新 更多