Link to home
Start Free TrialLog in
Avatar of jkna_gunn
jkna_gunn

asked on

paint methods on japplet help

below is some code i converted from a demo application on the sun website to make it into an applet.
its supposed to let you create hotspot rectangles, i have a vector of rectangle objects that will show existing rectangles.
now im trying to paint these ontop of the image but as i dont understand AWT or SWING very well, the place where i put the code
only shows the rectangles once i click the mouse,  can someone help so they show the rectangles as soon as the applet loads.
i also need code to check that any newly selected rectangle doesn't overlap with any of the existing rectangles.

-------------------------------------------------------------------------------------------------------------------------------------------
public class CreateHotSpotApplet extends JApplet {
    JLabel label;
    static String inputFile = "";
      public Vector points = new Vector();
      SelectionArea area = null;
   
    private void buildUI(Container container, ImageIcon image) {
        container.setLayout(new BoxLayout(container,
                                          BoxLayout.PAGE_AXIS));
                                         
        area = new SelectionArea(image, this);
        container.add(area);

        label = new JLabel("Drag your hotspot area within the image.");
        label.setLabelFor(area);
        container.add(label);

        //Align the left edges of the components.
        area.setAlignmentX(Component.LEFT_ALIGNMENT);
        label.setAlignmentX(Component.LEFT_ALIGNMENT); //redundant
    }

    public void updateLabel(Rectangle rect) {
        int width = rect.width;
        int height = rect.height;

        //Make the coordinates look OK if a dimension is 0.
        if (width == 0) {
            width = 1;
        }
        if (height == 0) {
            height = 1;
        }

        label.setText("You selected from ("
                      + rect.x + ", " + rect.y + ") to ("
                      + (rect.x + width - 1) + ", "
                      + (rect.y + height - 1) + ").");
    }

    /** Returns an ImageIcon, or null if the path was invalid. */
    protected static ImageIcon createImageIcon(String path) {
        java.net.URL imgURL = CreateHotSpotApplet.class.getResource(path);
        if (imgURL != null) {
            return new ImageIcon(imgURL);
        } else {
            System.err.println("Couldn't find file: " + path);
            return null;
        }
    }

    /**
     * Create the GUI and show it.  For thread safety,
     * this method should be invoked from the
     * event-dispatching thread.
     */
    private void createAndShowGUI() {
        //Make sure we have nice window decorations.
     
            JPanel p = new JPanel();

        //Create and set up the window.
        Container content = getContentPane();

        //Set up the content pane.
            buildUI(p,createImageIcon(inputFile));

            JMenuBar menuBar = new JMenuBar();
            JMenu file = new JMenu("File");

            JMenuItem exit = new JMenuItem("Save");
            exit.setActionCommand("save");
            file.add(exit);
            menuBar.add(file);

            this.setJMenuBar(menuBar);
 
            content.add(p);

    }

    public void init() {
            // get param
            inputFile = getParameter("inputFile");
            points.add(new Rectangle(297,101,20,37));
            points.add(new Rectangle(280,196,22,37));

            createAndShowGUI();
    }
   
    private class SelectionArea extends JLabel {
        Rectangle currentRect = null;
        Rectangle rectToDraw = null;
        Rectangle previousRectDrawn = new Rectangle();
        CreateHotSpotApplet controller;
   
        public SelectionArea(ImageIcon image, CreateHotSpotApplet controller) {
            super(image); //This component displays an image.
            this.controller = controller;
            setOpaque(true);
            setMinimumSize(new Dimension(10,10)); //don't hog space
   
            MyListener myListener = new MyListener();
            addMouseListener(myListener);
            addMouseMotionListener(myListener);

                  repaint();
        }
   
        protected void paintComponent(Graphics g) {
            super.paintComponent(g); //paints the background and image
   
            //If currentRect exists, paint a box on top.
            if (currentRect != null) {
                //Draw a rectangle on top of the image.
                g.setXORMode(Color.white); //Color of line varies
                                           //depending on image colors
                g.drawRect(rectToDraw.x, rectToDraw.y,
                           rectToDraw.width - 1, rectToDraw.height - 1);
   
                controller.updateLabel(rectToDraw);
                        drawExistingPoints(g);
            }
        }

            public void drawExistingPoints(Graphics g)
            {
                  Rectangle rec = null;
                  for (Enumeration e = controller.points.elements() ; e.hasMoreElements() ;) {
                         rec = (Rectangle)e.nextElement();
                         g.setXORMode(Color.white); //Color of line varies
                         g.drawRect(rec.x,rec.y,rec.width - 1, rec.height - 1);
                         //System.out.println(rec.x + ":" + rec.y + "--" + rec.width + ":" + rec.height);
                   }
            }
   
        private void updateDrawableRect(int compWidth, int compHeight) {
            int x = currentRect.x;
            int y = currentRect.y;
            int width = currentRect.width;
            int height = currentRect.height;
   
            //Make the width and height positive, if necessary.
            if (width < 0) {
                width = 0 - width;
                x = x - width + 1;
                if (x < 0) {
                    width += x;
                    x = 0;
                }
            }
            if (height < 0) {
                height = 0 - height;
                y = y - height + 1;
                if (y < 0) {
                    height += y;
                    y = 0;
                }
            }
   
            //The rectangle shouldn't extend past the drawing area.
            if ((x + width) > compWidth) {
                width = compWidth - x;
            }
            if ((y + height) > compHeight) {
                height = compHeight - y;
            }
         
            //Update rectToDraw after saving old value.
            if (rectToDraw != null) {
                previousRectDrawn.setBounds(
                            rectToDraw.x, rectToDraw.y,
                            rectToDraw.width, rectToDraw.height);
                rectToDraw.setBounds(x, y, width, height);
            } else {
                rectToDraw = new Rectangle(x, y, width, height);
            }
        }

             private class MyListener extends MouseInputAdapter {
            public void mousePressed(MouseEvent e) {
                int x = e.getX();
                int y = e.getY();
                currentRect = new Rectangle(x, y, 0, 0);
                updateDrawableRect(getWidth(), getHeight());
                repaint();
            }
   
            public void mouseDragged(MouseEvent e) {
                updateSize(e);
            }
   
            public void mouseReleased(MouseEvent e) {
                updateSize(e);
            }
   
            /*
             * Update the size of the current rectangle
             * and call repaint.  Because currentRect
             * always has the same origin, translate it
             * if the width or height is negative.
             *
             * For efficiency (though
             * that isn't an issue for this program),
             * specify the painting region using arguments
             * to the repaint() call.
             *
             */
            void updateSize(MouseEvent e) {
                int x = e.getX();
                int y = e.getY();
                currentRect.setSize(x - currentRect.x,
                                    y - currentRect.y);
                updateDrawableRect(getWidth(), getHeight());
                Rectangle totalRepaint = rectToDraw.union(previousRectDrawn);
                repaint(totalRepaint.x, totalRepaint.y,
                        totalRepaint.width, totalRepaint.height);
            }
        }
    }
}
Avatar of girionis
girionis
Flag of Greece image

>  //If currentRect exists, paint a box on top.
>             if (currentRect != null) {
>                 //Draw a rectangle on top of the image.
>                 g.setXORMode(Color.white); //Color of line varies
>                                            //depending on image colors
>                 g.drawRect(rectToDraw.x, rectToDraw.y,
>                            rectToDraw.width - 1, rectToDraw.height - 1);

>                 controller.updateLabel(rectToDraw);
>                     drawExistingPoints(g);
>             }

I think the problem for not showing the rectangles the first time should be in the above code. You only create them if the "currentRect" is not null. The first time it is called it is null and therefore the rectangles are not drawn in the screen. I would suggest adding an if statement that checks for nullness and then draws the rectangles:

if (currentRect == null)
{
    drawExistingPoints(g);
}

just before the if (currentRect != null) line. You could also just add the method call before that if statement and that should also work, although it will be called twice every time.

> i also need code to check that any newly selected rectangle doesn't
> overlap with any of the existing rectangles.

You will need to check the position of the newly drawn rectangle and compare it with the coordinates of the existing rectangles. If the coordinates are in the same space then you will have to make the newly created rectangles smaller and draw them right before the existing rectangles.
ASKER CERTIFIED SOLUTION
Avatar of girionis
girionis
Flag of Greece image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of jkna_gunn
jkna_gunn

ASKER

hi thanks for that, your right it was so simple i didn't even see it.
i put the method call to drawExistingPoints outside the if statement and it worked.

as for checking the rectangles i used the method intersects to detect if any existing rectangles are overlaping
Thank you for accepting, glad problem is solved :)