开发者

Lag when drawing something to move with mouse

I am having some trouble with drawing rectangles at the mouse position. The painted rectangle lags behind the mouse cursor when the mouse is moved. Is there a way to ensure the rectangle moves exactly on the mouse and does not lag behind?

Here is a little example, although because this is just a single rectangle the lag is very slight, but it is there. In the larger program I am painting a ton of them at a time though only moving the one.

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionListener;

import javax.swing.*;

public class MouseTest {
    JFrame window;
    DrawPanel content;

    public MouseTest(){
        window = new JFrame("Test");
        content = new DrawPanel();
        window.setContentPane(content);
        window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        window.setVisible(true);
        window.pack();
    }

    public static void main (String[] args)开发者_高级运维{
        MouseTest test = new MouseTest();
    }

    private class DrawPanel extends JPanel implements MouseMotionListener {
        int mouseX;
        int mouseY;

        private DrawPanel(){
            setBackground(Color.BLUE);
            setPreferredSize(new Dimension(400,400));
            addMouseMotionListener(this);
        }

        public void paintComponent(Graphics g){
            super.paintComponent(g);
            g.setColor(Color.RED);
            g.fillRect(mouseX, mouseY, 20, 20);
        }

        @Override
        public void mouseDragged(MouseEvent e) {
            // TODO Auto-generated method stub

        }

        @Override
        public void mouseMoved(MouseEvent e) {
            mouseX = e.getX();
            mouseY = e.getY();
            repaint();

        }
    }

}


Tthe first thing to do is move all of your Swing/AWT code into the EDT. In your application it may not matter, but it is a good habit to get into.

I couldn't reproduce your lag with either approach, however.

public static void main (String[] args)
{
    SwingUtilities.invokeLater(
        new Runnable()
        {
            public void run()
            {
                MouseTest test = new MouseTest();
            }
        });
}

See this article for more information on Swing Threading.


Maybe way off on this but when you say "lag behind" do you mean the cursor is not in the center of the rectangle? Your code has the cursor pointing to the top left corner of the rectangle, you need to offset it to center it.


Even if this is more work i recommend for any such task that you only invalidate and repaint the region that has changed. This will save many cycles (imagine drawing the complete backgound all the time...).

You will see great improvements.

EDIT

I tested it myself with this example

    public void mouseMoved(MouseEvent e) {
        repaint(mouseX, mouseY, 20, 20);
        mouseX = e.getX();
        mouseY = e.getY();
        repaint(mouseX, mouseY, 20, 20);
    }

and must admit the improvements are a little academic ( at least for my computer). Anyway, this technique should be used on more complex paint methods.. (where you finally will see improvements)

EDIT

And more cheat: If you still dislike the mismatch between where you think the cursor is and what the system thinks, try switch off the cursor (http://www.java2s.com/Code/Java/2D-Graphics-GUI/HidethemousecursoruseatransparentGIFasthecursor.htm) to give the user a better feedback.


The rectangle lags because your class processes every motion event. If it processed only the most recent event, then the rectangle would be up-to-date (although it might have large jumps in position). One way to do this is to run a separate thread that draws the rectangle based on the current mouse position, which is updated by the mouseMoved() method. You'll have to synchronize access to the mouse position variable.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜