Search code examples
javaswingmouselistenerresponsiveness

Java mouse listener lacking responsiveness


I made a little color selector using JPanels and mouse listeners, but for some reason the result isn't as responsive as expected and I don't know why.

custom color selector

in order to do so I created a modified JPanel I called ColorPanel, to add it a few properties like color and color name, built in mouse listener, background color defined when instanciated etc:

public class ColorPanel extends JPanel{

private Color color;
private String sColor;

public ColorPanel(Color color, String sColor){
    this.color = color;
    this.sColor = sColor;
    this.setBackground(color);
    this.setBorder(BorderFactory.createLineBorder(Color.white));
    this.addMouseListener(new appMouseListener());
    ColorSelector.panSelector.add(this);
    ColorSelector.vPanel.add(this);
}

public Color getColor(){
    return this.color;

}

public String getScolor(){
    return this.sColor;
}

class appMouseListener implements MouseListener {

    @Override
    public void mouseClicked(MouseEvent e) {
        // TODO Auto-generated method stub
        ColorSelector.select((ColorPanel)e.getSource());

    }

    @Override
    public void mouseEntered(MouseEvent arg0) {
        // TODO Auto-generated method stub

    }

    @Override
    public void mouseExited(MouseEvent arg0) {
        // TODO Auto-generated method stub

    }

    @Override
    public void mousePressed(MouseEvent arg0) {
        // TODO Auto-generated method stub

    }

    @Override
    public void mouseReleased(MouseEvent arg0) {
        // TODO Auto-generated method stub

    }

}

}

this is linked to another object I made meant to instanciate all the panels I need and their countainer, as well as the method to change the selected colorpanels border color and store its coulour into a global variable.

While it works, every so often I got to click several times to select a colorpanel. The program had no responsiveness problem before and that selector is the only thing behaving this way.

    public static void select(ColorPanel colorPanel) {



    IhmMap.SelectedColor = colorPanel.getColor();
    IhmMap.SelectedScolor = colorPanel.getScolor();

    for(int i = 0 ; i<vPanel.size(); i++ ){
        vPanel.elementAt(i).setBorder(BorderFactory.createLineBorder(Color.white));
    }

    colorPanel.setBorder(BorderFactory.createLineBorder(Color.red.darker().darker()));



}

This is the method, all the panels are added to a vector upon creation, so I can manipulate them easily.


Solution

  • MouseClicked event only fires if you didn't move the mouse at all between pressing and releasing the mouse. That way if you press the mouse button and move the mouse slightly just by 1 pixel, the mouseClicked won't get called.

    I suggest using mouseReleased or a combination of mousePressed, mouseReleased and/or mouseExited. e.g.

    private boolean pressed;
    
    @Override
    public void mouseExited(MouseEvent arg0) {
        pressed = false;
    }
    
    @Override
    public void mousePressed(MouseEvent arg0) {
        pressed = true;
    }
    
    @Override
    public void mouseReleased(MouseEvent arg0) {
        if (pressed) {
            //your code here
        }
    }
    

    That way you can press on the ColorPanel and as long as you don't leave the ColorPanel it will register a click.