Hi Jean,

I don't see any problems with the code and it works as expected (and documented). If a user clicks the left mouse button very fast and the MultiClickThreshhold value is big enough than only first action event on the button occurs and other clicks are discarded. I attached a test and it works fine for me.

I see what you'd expect. I don't have ideas why the current behavior is implemented in such way, may be other people will help you.. Anyway it's impossible to change the functionality because of backward compatibility.

Regards, Pavel
Hi,

I came across this some time ago while working on a project using JDK 6. I found the behaviour odd and looked at the source code for JDK 7 and was able find the code that was responsible for the odd behaviour.

Of course, it may well be intended behaviour, but to me it was surprising.

I have looked at the most recent release of the JDK 7 source code, and the behaviour is still as it was.

I call your attention to the mousePressed(MouseEvent e) function present at line 213 of BasicButtonListener (javax.swing.plaf.basic) :

public void mousePressed(MouseEvent e) {
       if (SwingUtilities.isLeftMouseButton(e) ) {
          AbstractButton b = (AbstractButton) e.getSource();

          if(b.contains(e.getX(), e.getY())) {
 long multiClickThreshhold = b.getMultiClickThreshhold();
              long lastTime = lastPressedTimestamp;
              long currentTime = lastPressedTimestamp = e.getWhen();
if (lastTime != -1 && currentTime - lastTime < multiClickThreshhold) {
                  shouldDiscardRelease = true;
                  return;
              }

             ButtonModel model = b.getModel();
             if (!model.isEnabled()) {
                // Disabled buttons ignore all input...
                return;
             }
             if (!model.isArmed()) {
                // button not armed, should be
                model.setArmed(true);
             }
             model.setPressed(true);
             if(!b.hasFocus() && b.isRequestFocusEnabled()) {
                b.requestFocus();
             }
          }
       }
    }

This behaviour seems odd to me because if one sets the threshold to 0.6 seconds for instance, and the user clicks every 0.5 seconds for whatever length of time, no mouse clicked event while be generated and application code while never get notified of any mouse click event. The behaviour I expected from setting the threshold in the JButton class was that the second click from the user would generate an event. Indeed, this seems like it would be the generally desired behaviours and appears to be the documented behaviour :

Copied from the JDK 7 API documentation :

Sets the amount of time (in milliseconds) required between mouse press events for the button to generate the corresponding action events. After the initial mouse press occurs (and action event generated) any subsequent mouse press events which occur on intervals less than the threshhold will be ignored and no corresponding action event generated. By default the threshhold is 0, which means that for each mouse press, an action event will be fired, no matter how quickly the mouse clicks occur. In buttons where this behavior is not desirable (for example, the "OK" button in a dialog), this threshhold should be set to an appropriate positive value.

Could someone let me know if I am missing something or if this is expected behaviour and why.

Jean-Remi Desjardins

n.b. The code to deliver the behaviour I expect would be something like this (but I haven't bothered compiling this so no promises) :

public void mousePressed(MouseEvent e) {
       if (SwingUtilities.isLeftMouseButton(e) ) {
          AbstractButton b = (AbstractButton) e.getSource();

          if(b.contains(e.getX(), e.getY())) {
 long multiClickThreshhold = b.getMultiClickThreshhold();
              long lastTime = lastPressedTimestamp;
              long currentTime = e.getWhen();
if (lastTime != -1 && currentTime - lastTime < multiClickThreshhold) {
                  shouldDiscardRelease = true;
                  return;
              }
else {
                  lastPressedTimestamp = currentTime;
              }

             ButtonModel model = b.getModel();
             if (!model.isEnabled()) {
                // Disabled buttons ignore all input...
                return;
             }
             if (!model.isArmed()) {
                // button not armed, should be
                model.setArmed(true);
             }
             model.setPressed(true);
             if(!b.hasFocus() && b.isRequestFocusEnabled()) {
                b.requestFocus();
             }
          }
       }
    }

package temp;

import javax.swing.*;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;

public class MultiClickThreshholdTest {
    public static void main(String[] args) throws Exception {
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                JButton button = new JButton("Button");

                button.setMultiClickThreshhold(2000);
                button.addActionListener(new ActionListener() {
                    public void actionPerformed(ActionEvent e) {
                        System.out.println("Fired");
                    }
                });

                JFrame frame = new JFrame();

                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.setSize(400, 400);
                frame.getContentPane().add(button);
                frame.setVisible(true);
            }
        });
    }
}

Reply via email to