Reputation: 2951
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.
Upvotes: 4
Views: 2906
Reputation: 152
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());
}
}
Upvotes: 4
Reputation: 9357
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){}
}
}
Upvotes: 0
Reputation: 1172
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");
}
}
}
Upvotes: 0
Reputation: 1745
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.
Upvotes: 2
Reputation: 310903
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.
Upvotes: 0
Reputation: 34900
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);
}
}
Upvotes: 1
Reputation: 8467
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
?
Upvotes: 0