[Webinar] Streamline your web hosting managementRegister Today

x
  • Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 372
  • Last Modified:

Array of Rectangles in Java Swing

I have some fairly simple code written that displays a square and lets the user move the square around the viewing window.  The end goal is to have multiple squares that the user can move around.  The number of squares will be dynamic; I will be reading a value off of a XML file at run time and that will be the number of squares created.  So I figure the best thing to do is the create an array of my class RedSquare that I use to define each square.  I cannot figure out how to do this. I have attached code of my current implementation.  The code builds fine however it fails when it goes to paint the square.  Any suggestions?

Thanks

-Jesse
import javax.swing.SwingUtilities;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.BorderFactory;
import java.awt.event.MouseEvent;
import java.awt.event.MouseAdapter;
import java.awt.*;
import java.util.*;




public class SwingPaintDemo4 {


    public static void main(String[] args) {

 
         SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                createAndShowGUI();
            }
        });
    }

    private static void createAndShowGUI() {
        System.out.println("Created GUI on EDT? "+
        SwingUtilities.isEventDispatchThread());
        JFrame f = new JFrame("Make My Lab");
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        f.add(new MyPanel());
        f.setSize(500,500);
        f.setVisible(true);
    }

}

class MyPanel extends JPanel {

    RedSquare[] redSquare = new RedSquare[2];
 

    public MyPanel() {

        setBorder(BorderFactory.createLineBorder(Color.black));



        addMouseListener(new MouseAdapter(){
            public void mousePressed(MouseEvent e){
                for(int i=0; i<2; i++){

                }
                if (redSquare[0].contains(e.getX(), e.getY())) {
                    moveSquare(e.getX(),e.getY());
                }
            }
        });

        addMouseMotionListener(new MouseAdapter(){
            public void mouseDragged(MouseEvent e){
                if (redSquare[0].contains(e.getX(), e.getY())) {
                    moveSquare(e.getX(),e.getY());
                }
            }
        });

    }

    public void moveSquare(int x, int y){

        // Current square state, stored as final variables
        // to avoid repeat invocations of the same methods.
        final int CURR_X = redSquare[0].getX();
        final int CURR_Y = redSquare[0].getY();
        final int CURR_W = redSquare[0].getWidth();
        final int CURR_H = redSquare[0].getHeight();
        final int OFFSET = 1;

        if ((CURR_X!=x) || (CURR_Y!=y)) {

            // The square is moving, repaint background
            // over the old square location.
            repaint(CURR_X,CURR_Y,CURR_W+OFFSET,CURR_H+OFFSET);

            // Update coordinates.
            redSquare[0].setX(x);
            redSquare[0].setY(y);

            // Repaint the square at the new location.
            repaint(redSquare[0].getX(), redSquare[0].getY(),
                    redSquare[0].getWidth()+OFFSET,
                    redSquare[0].getHeight()+OFFSET);
        }
    }

    public Dimension getPreferredSize() {
        return new Dimension(250,200);
    }

    public void paintComponent(Graphics g) {
        super.paintComponent(g);


        redSquare[0].paintSquare(g);
        //redSquare2[0].paintSquare(g);
        
    }


}

 class RedSquare{

    //public int i;
    private int xPos = 100;
    private int yPos = 50;
    private int width = 50;
    private int height = 50;

    public void setX(int xPos){
        this.xPos = xPos;
    }

    public int getX(){
        return xPos;
    }

    public void setY(int yPos){
        this.yPos = yPos;
    }

    public int getY(){
        return yPos;
    }

    public int getWidth(){
        return width;
    }

    public int getHeight(){
        return height;
    }

    public void paintSquare(Graphics g){
        g.setColor(Color.GREEN);
        g.fillRect(xPos,yPos,width,height);

    }
    public boolean contains(int x, int y){
        //if((x>= xPos && (x<xPos + 50)) && (y>= yPos && (y<=yPos +50))){
        if(x>= xPos && y>= yPos ){
            return true;
        }
        else
            return false;


        }
    }

Open in new window

0
jomille
Asked:
jomille
  • 2
2 Solutions
 
manavilaiCommented:
hi,

you have only initialized the array.you have actually not created the objects.

RedSquare[] redSquare = new RedSquare[2];

doing the below inside the MyPanel Constructor might help

redSquare[0] = new RedSquare();
redSquare[1] = new RedSquare();
0
 
kloeberCommented:
Jesse,

it's much simpler than you think ;)
try this:
import javax.swing.SwingUtilities;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.BorderFactory;
import java.awt.event.MouseEvent;
import java.awt.event.MouseAdapter;
import java.awt.*;


public class SwingPaintDemo4 {
    public static void main(String[] args) {
         SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                createAndShowGUI();
            }
        });
    }

    private static void createAndShowGUI() {
        System.out.println("Created GUI on EDT? "+
        SwingUtilities.isEventDispatchThread());
        JFrame f = new JFrame("Make My Lab");
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        f.add(new MyPanel());
        f.setSize(500,500);
        f.setVisible(true);
    }
}

class MyPanel extends JPanel {
    RedSquare[] redSquare =  { new RedSquare(100, 50, 50, 50), new RedSquare(200, 50, 50, 50) };
    Point dragPoint;
    RedSquare selectedRectangle;

    public MyPanel() {
        setBorder(BorderFactory.createLineBorder(Color.black));
        addMouseListener(new MouseAdapter(){
            @Override
            public void mousePressed(MouseEvent e){
                selectedRectangle = null;
                for (RedSquare r : redSquare){
                    if (r.contains(e.getPoint())) {
                        selectedRectangle = r;
                        dragPoint = e.getPoint();
                    }
                }
            }
        });
        addMouseMotionListener(new MouseAdapter(){
            @Override
            public void mouseDragged(MouseEvent e){
                try {
                    int dx = e.getX() - dragPoint.x;
                    int dy = e.getY() - dragPoint.y;
                    selectedRectangle.translate(dx, dy);
                    dragPoint = e.getPoint();
                    repaint();
                } catch (NullPointerException ex) { /* nothing to drag */ }
            }
        });
        setPreferredSize(new Dimension(250,200));
    }
    @Override
    public void paintComponent(Graphics g) {
        super.paintComponent(g);
        g.setColor(Color.green);
        for (RedSquare r : redSquare)
            g.fillRect(r.x, r.y, r.width, r.height);
    }
}

class RedSquare extends Rectangle {
    public RedSquare(int x, int y, int w, int h) {
        super(x, y, w, h);
    }
}

Open in new window

0
 
jomilleAuthor Commented:
Very nice.  That is much simpler than my initial implementation.  I edited the code a little but and created a seperate method to handle creating the array of recatgles since there will be a varying number of rectangles created at run-time.  

My next objective is to have a single number displayed on each rectangle I create.  I though I could simply add the line:

g.drawString(r.myNumber, r.x, r.y);

after

g.fillRect(r.x, r.y, r.width, r.height);

to display the number at the same place on each square each time it is re-drawn.  Is this the correct way to go about doing this?  

Thanks

-Jesse




import javax.swing.SwingUtilities;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.BorderFactory;
import java.awt.event.MouseEvent;
import java.awt.event.MouseAdapter;
import java.awt.*;


public class SwingPaintDemo4 {
    public static void main(String[] args) {
         SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                createAndShowGUI();
            }
        });
    }

    private static void createAndShowGUI() {
        System.out.println("Created GUI on EDT? "+
        SwingUtilities.isEventDispatchThread());
        JFrame f = new JFrame("Make My Lab");
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        f.add(new MyPanel());
        f.setSize(500,500);
        f.setVisible(true);
    }
}

class MyPanel extends JPanel {
   // RedSquare[] redSquare =  { new RedSquare(100, 50, 50, 50), new RedSquare(200, 50, 50, 50) };
    RedSquare[] redSquare = new RedSquare[5];




    Point dragPoint;
    RedSquare selectedRectangle;

    public MyPanel() {
        this.createSquares(5);
        setBorder(BorderFactory.createLineBorder(Color.black,3));
        addMouseListener(new MouseAdapter(){
            @Override
            public void mousePressed(MouseEvent e){
                selectedRectangle = null;
                for (RedSquare r : redSquare){
                    if (r.contains(e.getPoint())) {
                        selectedRectangle = r;
                        dragPoint = e.getPoint();
                    }
                }
            }
        });
        addMouseMotionListener(new MouseAdapter(){
            @Override
            public void mouseDragged(MouseEvent e){
                try {
                    int dx = e.getX() - dragPoint.x;
                    int dy = e.getY() - dragPoint.y;
                    selectedRectangle.translate(dx, dy);
                    dragPoint = e.getPoint();
                    repaint();
                } catch (NullPointerException ex) { /* nothing to drag */ }
            }
        });
        setPreferredSize(new Dimension(250,200));
    }
    @Override
    public void paintComponent(Graphics g) {

        super.paintComponent(g);
        g.setColor(Color.red);
        for (RedSquare r : redSquare)
           

            g.fillRect(r.x, r.y, r.width, r.height);
           // g.drawString(r.myNumber, r.x, r.y);
    }



    public void createSquares(int counter){
            int offset = 0;
             for( int i=0; i< counter; i++){
                redSquare[i] = new RedSquare(100+offset, 50, 50, 50);
                offset = offset + 55;
             }

        }

    }


class RedSquare extends Rectangle {
    public RedSquare(int x, int y, int w, int h) {
        super(x, y, w, h);
        int myNumber;
        
        

    }
}

Open in new window

0
 
kloeberCommented:
Depends on ;). x/y of your rectangle specify the top left corner. For drawing a string however x/y specifies the baseline position. In your case the string would be drawn above the rectangle. If that is what you want, you're all set. If you want the text inside the rectangle you'd need to calculate the x/y coordinates of the string based on the fontMetrics of the string.
0

Featured Post

Upgrade your Question Security!

Your question, your audience. Choose who sees your identity—and your question—with question security.

  • 2
Tackle projects and never again get stuck behind a technical roadblock.
Join Now