tags:

views:

689

answers:

5

For custom rendering, I've created a class that extends JPanel and overrides the paintComponent method. In the custom paintComponent I rendering multiple shape objects held in a array. What I would like to add is the ability to drag and select 1 or more of the shapes. While dragging I would like to show a translucent rectangle defining the selection region akin to what is seen in Windows Explorer. Can any provide a starting point for accomplishing this?

Thanks.

+1  A: 

You could use JXLayer. Span it across the whole form and do the painting in a custom LayerUI.

DR
A: 

Sure, here's an simple example with methods for creating and moving the shape.

class MyShape implements Shape {

   private Shape shape;

   public void createShape(Point p1, Point p2, ShapeType t) {
      switch(t) {
        case RECTANGLE: {
           shape = new Rectangle2D.Double(p1.x, p1.y, p2.x - p1.x, p2.y - p1.y);
           break;
        }
        ... (other shapes)
     }
  }

  public void moveShape(Point lastPoint, Point newPoint, ShapeType t) {
      int xOffset = newPoint.x - lastPoint.x;
      int yOffset = newPoint.y - lastPoint.y;
      switch(t) {
        case RECTANGLE: {
           double x1 = shape.getBounds().getX() + xOffset;
           double y1 = shape.getBounds().getY() + yOffset;
           double w = shape.getBounds().getWidth();
           double h = shape.getBounds().getHeight();
           shape = new Rectangle2D.Double(x1, y1, w, h);
           break;
        }
        ... (other shapes)
     }
  }
}
JRL
A: 

For some components ( I don't know if this apply to your components while being dragged ) you can set the background and use a "transparent color"

The Color class does implements Transparency.

To use it you may specify the alpha value in the Color constructor.

For instance this is a semi transparent black background:

         // 0: totally transparent 
         // 255: totally opaque, 
         // 192 semy transparent.
         this.setBackground(new Color( 0, 0, 0, 192 ));

See the [constructor][1]

Again, I'm not sure if this applies to you. Give it a try

[1]: http://java.sun.com/javase/6/docs/api/java/awt/Color.html#Color(int, int, int, int)

OscarRyz
+2  A: 

I saw an interesting way of doing this in JFreeChart's source code. You can draw a marquee over a section of the chart, and when you release the mouse the chart zooms in on the selected are. Re-rending the chart is expensive and unfortunately JFreeChart doesn't support partial paints of a chart. So to draw the marquee they do some sort of bitwise operation to the colors of the component, in a reversible fashion. Every time the mouse moves while selecting a marquee, you reverse the previous bitwise operation on the old coordinates, then redo it on the new coordinates.

Take a look at ChartPanel.java in JFreeChart

private void drawZoomRectangle(Graphics2D g2) {
    // Set XOR mode to draw the zoom rectangle
    g2.setXORMode(Color.gray);
    if (this.zoomRectangle != null) {
        if (this.fillZoomRectangle) {
            g2.fill(this.zoomRectangle);
        }
        else {
            g2.draw(this.zoomRectangle);
        }
    }
    // Reset to the default 'overwrite' mode
    g2.setPaintMode();
}
Sam Barnum
A: 

All,

Thanks for the suggestions. Ended up resolving this by adapting some the code used in this rather clever demo. http://forums.sun.com/thread.jspa?threadID=5299064&start=19

public class ExamplePanel extends JPanel
{
    Rectangle2D.Double selectionRect;
    Point mouseDown, mouseHere;

   ...

    protected void paintComponent(Graphics g)
    {
        AlphaComposite ta = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.1f);
        g2d.setComposite(ta);
        g2d.setColor(Color.BLUE);
        g2d.fill(selectionRect);
        g2d.setComposite(AlphaComposite.SrcOver);
        g2d.setColor(Color.BLACK);
        g2d.draw(selectionRect);
    }
}

public class ExammpleMouseListener extends MouseAdapter    
{    
    @Override
    public void mousePressed(MouseEvent e)
    {      
        super.mousePressed(e);

        // store the mouse down location
        pnl.mouseDown = e.getPoint();
    }

 /**
  * @see  java.awt.event.MouseAdapter#mouseDragged(java.awt.event.MouseEvent)
  */
 @Override
 public void mouseDragged(MouseEvent e)
 {
  super.mouseDragged(e);

  // check for left mouse button
  if ((e.getModifiersEx() & InputEvent.BUTTON1_DOWN_MASK) == 0)
  {
   return;
  }

  // store the current location
  pnl.mouseHere = e.getPoint();

  // calculate the size of the selection rectangle
  double downX = pnl.mouseDown.getX();
  double downY = pnl.mouseDown.getY();
  double hereX = pnl.mouseHere.getX();
  double hereY = pnl.mouseHere.getY();

  double l = Math.min(downX, hereX);
  double t = Math.min(downY, hereY);
  double w = Math.abs(downX - hereX);
  double h = Math.abs(downY - hereY);

  pnl.selectionRect = new Rectangle2D.Double(l, t, w, h);

  // queue a repaint of the panel
  pnl.repaint();
 }

 @Override
 public void mouseReleased(MouseEvent e)
 {
  super.mouseReleased(e);

  // clear the selection rectangle
  pnl.selectionRect = null;

  // queue a repaint of the panel
   pnl.repaint();
  }
 }
}
javacavaj