【问题标题】:Generic class to detect triple click without firing double- or single-click用于检测三次单击而不触发双击或单击的通用类
【发布时间】:2015-02-28 05:09:06
【问题描述】:

编辑-基于接受的答案的更正代码显示在这篇文章的底部。

我找到了一种方法 (written by Andremoniy) 可以在不触发单击和双击的情况下捕获双击和三次单击。它非常适合我的目的。

我对其进行了修改,以便它可以通过实现调整点击间隔。这也很有效。

我的修改包括将其设为abstract class,定义实现必须定义的 5 个abstract 方法(用于单次、双次、三次和“多次”点击的方法以及点击间隔调整器)。

这是修改后的版本(println 语句具有指导意义):

public abstract class Click123 extends JPanel  
{
  public abstract void singleClick();
  public abstract void doubleClick();
  public abstract void tripleClick();  
  public abstract void manyClick();
  public abstract int  getFreq(); 

  public Click123()
  {
    addMouseListener
    (
      new MouseAdapter() 
      {
        Thread cp = null;

        public void mouseClicked(MouseEvent e) 
        {
          if (cp != null && cp.isAlive())
            cp.interrupt(); 

          if (e.getClickCount() == 1) 
          {
            cp =  new Thread(new ClickProcessor(new Callable<Void>() {
              @Override public Void call() throws Exception {
                singleClick();
                return null;
              }
            }));
            cp.start();
          }
          else if (e.getClickCount() == 2) 
          {
            cp = new Thread(new ClickProcessor(new Callable<Void>() {
              @Override public Void call() throws Exception {
                doubleClick();
                return null;
              }
            }));
            cp.start();
          }
          else if (e.getClickCount() == 3) 
          {
            cp =  new Thread(new ClickProcessor(new Callable<Void>() 
            {
              @Override public Void call() throws Exception {
                tripleClick();
                return null;
              }
              })              
            );
            cp.start();
          }
          else manyClick();
        } // mouseClicked
      }  // new MouseAdapter
    ); // add mouseListener
  } // Click123  

  class ClickProcessor implements Runnable 
  {
    Callable<Void> eventProcessor;

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

    @Override public void run() 
    {
      try 
      {
          Thread.sleep(getFreq());
          eventProcessor.call();
      } catch (InterruptedException e) { System.out.println(e);} 
        catch (Exception e)            { System.out.println(e);}
    }  // run
  }  // class ClickProcessor
} // class Click123

这是实施程序:

public class NewMain1 {
  static int INITIAL_CLICK_FREQUENCY = ((Integer)Toolkit.getDefaultToolkit()
      .getDesktopProperty("awt.multiClickInterval"));

  public static int CLICK_FREQUENCY;

  static       JSpinner spinner   = new JSpinner();
  static final JLabel   ch        = new JLabel("Click here to test");

  public static void main(String[] args) {

    CLICK_FREQUENCY = INITIAL_CLICK_FREQUENCY;
    spinner = new JSpinner();
    spinner.setModel(new SpinnerNumberModel(CLICK_FREQUENCY, 200, 900, 50));
    spinner.addChangeListener(new ChangeListener() {
      @Override
      public void stateChanged(ChangeEvent e) {
        CLICK_FREQUENCY = (int) spinner.getValue();
      }
    });

    Click123 frame = new Click123(){ 
      public void singleClick(){
        JOptionPane.showMessageDialog(null,"Single click at " + CLICK_FREQUENCY);
      }
      public void doubleClick(){
        JOptionPane.showMessageDialog(null,"Double click at " + CLICK_FREQUENCY);
      }
      public void tripleClick(){
        JOptionPane.showMessageDialog(null,"Triple click at " + CLICK_FREQUENCY);
      }
      public void manyClick(){
        JOptionPane.showMessageDialog(null,"Many clicks at " + CLICK_FREQUENCY);  
      }
      public int getFreq(){
        return CLICK_FREQUENCY; 
      }
    };
    frame.setDefaultCloseOperation(DISPOSE_ON_CLOSE);
    frame.setLayout(new FlowLayout());
    frame.setSize(500, 300);
              ch.setBorder(new EtchedBorder());
    frame.add(ch);
    frame.add(spinner);
    frame.setVisible(true);
  } // main
}

如最初所写,Click123 extends JFrame。我修改了它(通过将顶行更改为extends JTextField)以使用JTextField 类型的网格。然后我添加了一个按钮来动态更改点击间隔。所以现在我有三个相同的(除了扩展类型)大块代码。

我的问题是这样的:我如何修改Click123,以便在不做任何改动的情况下,让任何组件都能识别单击、双击和三次单击?

编辑——必要更改摘要(对于我自己的应用程序,abstract 方法需要传递 MouseEvent 以确定哪个组件触发了点击):

类定义:

 public abstract class Click123<T extends Component>  
 {
   public abstract void singleClick(MouseEvent e); // same for 3 others
    ...

    public Click123(T target)
    {
      target.addMouseListener
      (
        new MouseAdapter() ...
     } ...
  }

final 添加为修饰符以传递MouseEvent

    public void mouseClicked(final MouseEvent e) 

通过MouseEvent:

    singleClick(e); // same for doubleClick and tripleClick and manyClick

接收MouseEvent 以确定哪个组件触发了点击:

  public void doubleClick(MouseEvent e)

实施:

frame = new JPanel();
new Click123(frame) {

【问题讨论】:

  • 您好,抱歉,您的原始代码的哪一部分需要取出才能添加您添加的解决方案?谢谢。

标签: java generics abstract-class


【解决方案1】:

泛型不是必需的。您只需将MouseListener 添加到Component

public abstract class Click123 // doesn't extend anything
{
    public Click123(Component comp)
    {
        comp.addMouseListener(new MouseAdapter() {
           // ...
        }));
    }
}

现在你可以传递JFrame,或者你想要的任何Component

Click123 handler = new Click123(myJFrame){ 
  public void singleClick(){
    JOptionPane.showMessageDialog(null,"Single click at " + CLICK_FREQUENCY);
  }
  // Other implementing methods here
}

【讨论】:

  • @rgettman--在看到下面 k_g 的答案后,我花了 30 分钟修复我的代码后才找到你的答案。稍后我将研究您的更简单的解决方案。我很高兴我能让傻瓜工作!
【解决方案2】:

泛型是解决方案的一部分。只需执行以下操作:

  1. 让你的班级Click123&lt;T extends Component&gt;
  2. 让你的构造函数public Click123(T targetedComponent) {
  3. 请致电targetedComponent.addMouseListener 而不是addMouseListener
  4. 创建JFrameJPanel 或其他任何内容,然后将其作为构造函数参数传递给您的new Click123。然后在您使用 Click123 的地方使用您的 JFrame

【讨论】:

  • 谢谢你,@k_g!我在您发布后的 1 分钟内找到了您的答案,但我花了 30 分钟来实施,因为在我的挫折中,我已经丢弃了抽象方法的所有正确参数列表并且没有立即意识到它。我很接近,是吗?我将编辑我的原始帖子以表示实际的工作代码。
  • @DSlomer64 不客气,是的,你非常接近。顺便说一句,不要编辑您的原始帖子以包含工作代码,因为这将使该网站的未来查看者更难理解正在发生的事情。修改可能会被回滚。
  • 谢谢。我认为编辑原始帖子更可取。我会发布我更正的代码作为答案,是吗?
  • @DSlomer64 不,这也没有必要。任何人都应该能够将您的问题与我的答案结合起来以获得正确的代码。
  • 在阅读您的最后一条评论之前,我“妥协”了,认为我需要做点什么。编辑在开始时是单行的,最后是一个连续的小块。如果他们需要去,那很容易。
【解决方案3】:

根据要求,我发布了有效的代码。原始帖子中的编辑过于分散而无用。原始代码修改用 ////////// 标记。

package clickForm;

import java.awt.Component;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.concurrent.Callable;    

public abstract class Click123<T extends Component>  ////////////////
{
  public abstract void singleClick(MouseEvent e); ////////////////
  public abstract void doubleClick(MouseEvent e); ////////////////
  public abstract void tripleClick(MouseEvent e); ////////////////
  public abstract void manyClick(MouseEvent e);   ////////////////
  public abstract int  getFreq(); 

  public Click123(T target)  ////////////////
  {
    target.addMouseListener  ////////////////
    (
      new MouseAdapter()   ////////////////
      {
        Thread cp = null;

        public void mouseClicked(final MouseEvent e) 
        {
          if (cp != null && cp.isAlive())
            cp.interrupt(); 

          if (e.getClickCount() == 1) 
          {
            cp =  new Thread(new ClickProcessor(new Callable<Void>() {
              @Override public Void call() throws Exception {
                singleClick(e); //////////////////////////////////////////
                return null;
              }
            }));
            cp.start();
          }
          else if (e.getClickCount() == 2) 
          {
            cp = new Thread(new ClickProcessor(new Callable<Void>() {
              @Override public Void call() throws Exception {
                doubleClick(e); //////////////////////////////////////////
                return null;
              }
            }));
            cp.start();
          }
          else if (e.getClickCount() == 3) 
          {
            cp =  new Thread(new ClickProcessor(new Callable<Void>() 
            {
              @Override public Void call() throws Exception {
                tripleClick(e); //////////////////////////////////////////
                return null;
              }
              })              
            );
            cp.start();
          }
          else manyClick(e); //////////////////////////////////////////
        } // mouseClicked
      }  // new MouseAdapter
    ); // add mouseListener
  } // Click123  

  class ClickProcessor implements Runnable 
  {
    Callable<Void> eventProcessor;

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

    @Override public void run() 
    {
      try 
      {
          Thread.sleep(getFreq());
          eventProcessor.call();
      } catch (InterruptedException e) { System.out.println(e);} 
        catch (Exception e)            { System.out.println(e);}
    }  // run
  }  // class ClickProcessor
} // class Click123

实施:

package clickForm;

import java.awt.FlowLayout;
import java.awt.Toolkit;
import java.awt.event.MouseEvent;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JSpinner;
import javax.swing.SpinnerNumberModel;
import static javax.swing.WindowConstants.DISPOSE_ON_CLOSE;
import javax.swing.border.EtchedBorder;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;   

public class Main {

static int CLICK_FREQUENCY = (int) Toolkit.getDefaultToolkit().getDesktopProperty("awt.multiClickInterval");

  static       JSpinner spinner   = new JSpinner();
  static final JLabel   ch        = new JLabel("Click here to test");
  static       JFrame   frame     = new JFrame();

  public static void main(String[] args) {

    spinner = new JSpinner();
    spinner.setModel(new SpinnerNumberModel(CLICK_FREQUENCY, 200, 900, 50));
    spinner.addChangeListener(new ChangeListener() {
      @Override
      public void stateChanged(ChangeEvent e) {
        CLICK_FREQUENCY = (int) spinner.getValue();
      }
    });

    new Click123(ch){   /////////////////////////////////////////////

      @Override
      public void singleClick(MouseEvent e) { //////////////////////////////
        JOptionPane.showMessageDialog(null,"Single at " + CLICK_FREQUENCY);
      }

      @Override
      public void doubleClick(MouseEvent e) { //////////////////////////////
        JOptionPane.showMessageDialog(null,"Double at " + CLICK_FREQUENCY);
      }

      @Override
      public void tripleClick(MouseEvent e) { //////////////////////////////
         JOptionPane.showMessageDialog(null,"Triple at " + CLICK_FREQUENCY);
      }

      @Override
      public void manyClick(MouseEvent e) { //////////////////////////////
        JOptionPane.showMessageDialog(null,"Many at " + CLICK_FREQUENCY);  
      }

      @Override
      public int getFreq() {
        return CLICK_FREQUENCY;
      }
    };
    frame.setDefaultCloseOperation(DISPOSE_ON_CLOSE);
    frame.setLayout(new FlowLayout());
    frame.setSize(500, 300);
              ch.setBorder(new EtchedBorder());
    frame.add(ch);
    frame.add(spinner);
    frame.setVisible(true);
  } // main
}

【讨论】:

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