I can think at two methods:

1. During the drag operation draw only the objects that are moving
with a XOR operation. It can look like this (selectedObjects can be a
List of your graphic objects):

public void mouseDragged( MouseEvent e ) {
     if (selectedObjects.size() == 0)
         return;

     Graphics g = getGraphics();
     g.setXORMode(Color.white);
     drawObjects(selectedObjects, g);
     updatePosition(selectedObjects, e.getX(), e.getY());
     drawObjects(selectedObjects, g);
     g.dispose();
}

I think it is obvious what drawObjects and updatePosition methods are
supposed to do.

2. You can draw the fixed objects in an BufferedImage.

3. The Graphics2D accepts a Shape for the clipping area. So you can
compute the outline of your selected objects and update only the
inside of this shape. I am not sure if this brings much or just slow
everything down. Probably it depends on the complexity of the graphic
objects you want to draw.


I am also interested to find out more ideas.

-Iulian

David Eisner wrote:

> Attached is a toy program that draws a thousand colored
> rectangles, and allows the user to drag them around
> with the mouse.
>
> Initially, I didn't pass any arguments to repaint(), so
> that all the rectangles were wastefully re-rendered.
> This made dragging very slow -- the dragged rectangle
> would lag the mouse, and only catch up at the end.
>
> By calculating a sensible clip bound and re-rendering
> only the rectangles in that region, the performance
> was much better.
>
> Now I've added two rectangles at the bottom of the window that
> are connected by a line.  As a linked rectangle is dragged
> such that the line intersects the field of rectangles,
> the repaint region becomes larger and the performance
> is poor again -- the rectangle lags behind the mouse
> (try dragging the blue rectangle up the right side
> of the window).
>
> This isn't a real-world program, but I'm wondering how one
> would improve the performance -- with the hope that any such
> improvements might be applicable elsewhere.
>
> Thanks.
>
> -David
>
>
> ------------------------+--------------------------+
> David Eisner            | E-mail: [EMAIL PROTECTED]   |
> CALCE EPSC              | Phone:  301-405-5341     |
> University of Maryland  | Fax:    301-314-9269     |
> ------------------------+--------------------------+
>
>
> ------------------------------------------------------------------------
>
> import java.awt.*;
> import java.awt.event.*;
> import javax.swing.*;
>
>
> /**
>  *  Toy app to demonstrate performance issue.
>  */
> public class RectangleTest extends JFrame {
>
>     GraphPanel main_panel;
>
>
>     public RectangleTest() {
>         super("RectangleTest v0.01");
>
>
>         addWindowListener( new WindowAdapter() {
>             public void windowClosing( WindowEvent e) {
>                 System.exit(0);
>             }
>
>         });
>
>         main_panel = new GraphPanel();
>         main_panel.setPreferredSize( new Dimension( Constants.WIN_WIDTH,
>                                                     Constants.WIN_HEIGHT ));
>         main_panel.setBackground( Color.white );
>         getContentPane().add( main_panel, BorderLayout.CENTER );
>     }
>
>
>
>     public static void
>     main( String args[] ) {
>
>         RectangleTest app = new RectangleTest();
>
>         app.pack();
>         app.setVisible(true);
>     }
> }
>
>
>
> class Constants {
>     final static int WIN_WIDTH = 650;
>     final static int WIN_HEIGHT = 450;
> }
>
>
> ------------------------------------------------------------------------
>
>
> import java.awt.*;
> import java.awt.event.*;
> import java.awt.geom.*;
> import java.util.*;
>
> import javax.swing.*;
> import javax.swing.event.*;
>
> /**
>  * JPanel that can display a bunch of colored rectangles.
>  */
> public class GraphPanel extends JPanel  {
>
>     Random rg = new Random();
>
>     Vector rects = new Vector(); // list of ColoredRectangles
>     Link   link;
>
>     Rectangle2D selectedRect = null;
>     Point   dragStartPt = null;
>     Point   rectStartPt = new Point();
>
>     final static int NUM_RECTS = 1000;
>
>     /**
>      *  Rectangle with a color.
>      */
>     class ColoredRectangle extends Rectangle2D.Double {
>
>         private Color color;
>
>         ColoredRectangle( int x, int y, int w, int h ) {
>             this(x, y, w, h, Color.white );
>         }
>
>         ColoredRectangle( int x, int y, int w, int h, Color c ) {
>             super( x, y, w, h );
>             color = c;
>
>         }
>
>         public void
>         setColor( Color c ) {
>             color = c;
>         }
>
>         public Color
>         getColor() {
>             return color;
>         }
>
>     }
>
>
>     /**
>      * A simple link between two rectangles.
>      */
>     class Link {
>
>         Rectangle2D r1;
>         Rectangle2D r2;
>
>         Link( Rectangle2D rect1, Rectangle2D rect2 ) {
>             r1 = rect1;
>             r2 = rect2;
>         }
>     }
>
>
>     public GraphPanel() {
>         super();
>
>         Rectangle2D rect;
>
>         rect = new ColoredRectangle( 20, Constants.WIN_HEIGHT - 50,
>                                      25, 25, Color.red );
>         rects.add( rect );
>
>         rect = new ColoredRectangle( Constants.WIN_WIDTH - 50,
>                                      Constants.WIN_HEIGHT - 50,
>                                      25, 25, Color.blue );
>         rects.add( rect );
>
>
>         for (int i= rects.size(); i < NUM_RECTS; i++) {
>             rect = new ColoredRectangle( rg.nextInt( Constants.WIN_WIDTH - 100),
>                                          rg.nextInt( Constants.WIN_HEIGHT -100),
>                                          5 + rg.nextInt( 40 ),
>                                          5 + rg.nextInt( 40 ),
>                                          new Color( rg.nextInt( 256 ),
>                                                     rg.nextInt( 256 ),
>                                                     rg.nextInt( 256 ) ));
>             rects.add( rect );
>         }
>
>         link = new Link( (Rectangle2D) rects.get(0),
>                          (Rectangle2D) rects.get(1) );
>
>
>         MouseInputAdapter adapter = new MouseInputAdapter() {
>             public void mousePressed( MouseEvent e ) {
>
>                 Point pt = e.getPoint();
>
>                 selectedRect = pickRectangle( pt );
>                 if (selectedRect != null) {
>                     dragStartPt = pt;
>                     rectStartPt.setLocation( selectedRect.getX(),
>                                              selectedRect.getY() );
>                 }
>             }
>
>             public void mouseDragged( MouseEvent e ) {
>                 if (selectedRect != null) {
>                     double deltaX = e.getX() - dragStartPt.getX();
>                     double deltaY = e.getY() - dragStartPt.getY();
>
>                     // Calculate bounds for repaint
>                     Rectangle bounds = selectedRect.getBounds();
>
>                     selectedRect.setRect( rectStartPt.getX() + deltaX,
>                                           rectStartPt.getY() + deltaY,
>                                           selectedRect.getWidth(),
>                                           selectedRect.getHeight() );
>                     bounds.add( selectedRect );
>
>                     // Make sure bounds includes Link line
>                     if (link.r1 == selectedRect)
>                         bounds.add( link.r2 );
>                     else if (link.r2 == selectedRect)
>                         bounds.add( link.r1 );
>
>                     bounds.width += 1;
>                     bounds.height += 1;
>                     repaint( bounds  );
>                 }
>             }
>
>
>             public void mouseReleased( MouseEvent e ) {
>                 selectedRect = null;
>                 dragStartPt = null;
>             }
>         };
>
>         addMouseListener( adapter );
>         addMouseMotionListener( adapter );
>     }
>
>
>     public void
>     paintComponent( Graphics g ) {
>         Graphics2D g2 = (Graphics2D) g;
>         Rectangle cb = g2.getClipBounds();
>         cb.x -= 1;
>         cb.y -= 1;
>         cb.width += 1;
>         cb.height += 1;
>
>         super.paintComponent( g2 );
>
>         Line2D.Double line = new Line2D.Double( link.r1.getCenterX(),
>                                                 link.r1.getCenterY(),
>                                                 link.r2.getCenterX(),
>                                                 link.r2.getCenterY() );
>
>         g2.setColor( Color.black );
>         g2.draw( line );
>         for (int i=0; i < rects.size(); i++) {
>             ColoredRectangle  rect = (ColoredRectangle) rects.get(i);
>
>             if ( rect.intersects( cb )) {
>                 g2.setColor( rect.getColor() );
>                 g2.fill( rect );
>                 g2.setColor( Color.black );
>                 g2.draw( rect );
>             }
>         }
>
>     }
>
>     /**
>      * Return rectangle that contains pt, if any, or null otherwise.
>      */
>     private Rectangle2D
>     pickRectangle( Point pt ) {
>
>         double x = pt.getX();
>         double y = pt.getY();
>
>         for (int i=rects.size() - 1; i >= 0; i--) {
>             Rectangle2D rect = (Rectangle2D) rects.get(i);
>             if (rect.contains( x, y))
>                 return rect;
>         }
>         return null;
>     }
>
> }
>

===========================================================================
To unsubscribe, send email to [EMAIL PROTECTED] and include in the body
of the message "signoff JAVA2D-INTEREST".  For general help, send email to
[EMAIL PROTECTED] and include in the body of the message "help".

Reply via email to