Search code examples
javaswingdrag-and-dropglasspane

Java Swing GlassPane Drag Performance


I'm trying to do a visual drag and drop in my Swing application using a GlassPane, but am running into the problem that the drag image lags behind the mouse pointer, sometimes considerably. How do I solve this? My GlassPane code is below. Thanks!

package dragui;

import java.awt.*;
import javax.swing.*;
import java.awt.event.MouseEvent;
import javax.swing.event.MouseInputAdapter;

public class GlassPane extends JComponent {
    private int x=0, y=0, k=25,z=1;
    private boolean showDot;
    private MouseInputAdapter mia = new MouseInputAdapter(){

        @Override
        public void mouseDragged(MouseEvent me) {
            setPos(me.getX(), me.getY());
        }

        @Override
        public void mousePressed(MouseEvent me) {
            setShow(true);
            setPos(me.getX(), me.getY());   
        }

        @Override
        public void mouseReleased(MouseEvent me){
            setShow(false);
            setVisible(false);
        }
    };

    public void setShow(boolean b){ this.showDot = b; }

    public void paint(Graphics g) {
        if (showDot) {
            g.setColor(new Color(0.0f, 0.25f, 1.0f));
            g.fillOval(x - k, y - k, 2*k, 2*k);
        }
    }

    public void setPos(int x, int y) {
        int tmpX = this.x, tmpY = this.y; 
        this.x = x; this.y = y;
        repaint(tmpX - k , tmpY-k, 2*k+5, 2*k+5);
        repaint(this.x-k, this.y-k, 2*k+5, 2*k+5);        
    }

    public GlassPane() {
        addMouseListener(mia); 
        addMouseMotionListener(mia);
        setOpaque(false);
    }
}

Solution

  • According to the Javadoc,

    A subclass that just wants to specialize the UI (look and feel) delegate's paint method should just override paintComponent.

    And this is because paint(...) actually delegates the work of painting to three protected methods: paintComponent, paintBorder, and paintChildren. That being said, try replacing paint(...) with this

    @Override
    protected void paintComponent(Graphics g) {
        if (showDot) {
            Graphics gCopy = g.create();
    
            gCopy.setColor(new Color(0.0f, 0.25f, 1.0f));
            gCopy.fillOval(x - k, y - k, 2*k, 2*k);
    
            gCopy.dispose();
        }
    }