Sk4llsRPG
Sk4llsRPG

Reputation: 259

Calling paint() from another method in Java

what I am trying to achieve in Java is to be able to paint random shapes from another method without having to have those shapes already drawn from the start (user picks x, y, w, h themselves)

Here is what I have so far:

public class Design extends JComponent {
private static final long serialVersionUID = 1L;

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

public void drawRect(int xPos, int yPos, int width, int height) {
    Graphics g = null;
    g.drawRect(width, height, xPos, yPos);
}
}

As you can see above, I have the drawRect function coded but do not understand how to make it so when I call the drawRect() function, it gets the paint() function to draw a rectangle instead which is EXACTLY what the paint function does, inside it, you type g.drawRect() and your x,y,w,h. The reason why I am doing this and not just straight up using paint() is because i'm trying to make a component so instead of having to type out the paint() function everytime, I just add this class to my Swing and it's done.

Hope you understand what I'm trying to achieve here. Thanks.

Upvotes: 1

Views: 5884

Answers (2)

MadProgrammer
MadProgrammer

Reputation: 347194

The first thing you need to do is let go of the idea that you can control the paint process, you can't, you can respond to paint events and make requests to the RepaintManager that an update might be needed.

Basically, you don't call paint directly, paint is called in response to the RepaintManager wanting something painted.

Take look at Painting in AWT and Swing and Performing Custom Painting.

On to your code. Don't override paint and certainly don't circumvent the paint process, instead, it should look something more like this...

@Override
protected void paintComponent(Graphics g) {
    super.paintComponent(g);
    drawRect(g, 10, 10, 10, 10);
}

protected void drawRect(Graphics g, int xPos, int yPos, int width, int height) {
    g.drawRect(xPos, yPos, width, height);
}

Graphics#drawRect actually takes parameters x, y, width, height in that order...

The reason why I am doing this and not just straight up using paint() is because i'm trying to make a component so instead of having to type out the paint() function every time

Doesn't make sense, that's the point of having the paint methods, so you can customise the way a component is paint, make lots of instances of it and add it your GUI...this is how all the Swing controls work...

Also, you might find 2D Graphics of interest

Updated based on comments

So, you want a method that some other object can call and it will enable them to add a "rectangle" to the the existing object/component...

Start by defining an instance variable of Rectangle

private Rectangle rectangle;

In your paintComponent, check to see if rectangle is null or not and if it's not, paint it...

protected void paintComponent(Graphics g) {
    super.paintComponent(g);
    if (rectangle != null)  {
        Graphics2D g2d = (Graphics2D)g;
        g2d.draw(rectangle);
    }
}

Now, update your drawRect method to create an instance Rectangle and request that the component be repainted

public void drawRect(int xPos, int yPos, int width, int height) {
    rectangle = new Rectangle(xPos, yPos, width, height);
    repaint();
}

For example...

public class Design extends JComponent {

    private Rectangle rectangle;

    protected void paintComponent(Graphics g) {
        super.paintComponent(g);
        if (rectangle != null)  {
            Graphics2D g2d = (Graphics2D)g;
            g2d.draw(rectangle);
        }
    }

    public void drawRect(int xPos, int yPos, int width, int height) {
        rectangle = new Rectangle(xPos, yPos, width, height);
        repaint();
    }
}

Now, if you want to support having multiple rectangles, you could simply use a List and add as many instances Rectangle as you want, iterating over the List in the paintComponent method

Upvotes: 2

alex2410
alex2410

Reputation: 10994

You need to do all paintings inside paintComponent() method with calling super.paintComponent().

I suggest you to store all needed shapes in List and draw all of them in paintComponent(). Instead of drawRect use something like addRect which adding new shape to your List and call repaint() method. Examine next simple example:

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.Shape;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;

import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JFrame;

public class TestFrame extends JFrame {

    public TestFrame() {
        System.out.println("as".equalsIgnoreCase(null));
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        init();
        pack();
        setVisible(true);
    }

    private void init() {
        final Design d = new Design();
        d.addRect(0,0,10,20);

        JButton b = new JButton("add");
        b.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {
                Random r = new Random();
                int w = r.nextInt(100);
                int h = r.nextInt(100);
                d.addRect(0,0,w,h);
            }
        });
        add(d);
        add(b,BorderLayout.SOUTH);
    }

    public static void main(String... strings) {
        new TestFrame();
    }

    private class Design extends JComponent {
        private static final long serialVersionUID = 1L;

        private List<Shape> shapes = new ArrayList<Shape>();

        public void paint(Graphics g) {
            super.paintComponent(g);
            Graphics2D g2d = (Graphics2D) g;
            for(Shape s : shapes){
                g2d.draw(s);
            }
        }

        public void addRect(int xPos, int yPos, int width, int height) {
            shapes.add(new Rectangle(xPos,yPos,width,height));
            repaint();
        }

        @Override
        public Dimension getPreferredSize() {
            return new Dimension(100,100);
        }

    }

}

Upvotes: 1

Related Questions