Whenever Java needs to draw something to the screen, it relies on thepaint method. With Swing components such as TextArea, the paint method is called automatically, and we didn’t have to worry about it because we were ok with it drawing the way it is defined by default. When we deal with custom graphics such as circles, we have to start to define the paint method to suit our needs.

The Graphics Class and Paint Method

The paint method is a part of the abstract class Graphics. Every component in Java that can be drawn on the screen will have a Graphics object, which keeps track of things such as where on the screen the component is drawn. When we need to draw graphics to the screen, we will rely on methods from the Graphics object to be able to define and manipulate parameters related to the drawing.

When we first initialize our Swing GUI, the paint method is called by the Event Dispatch Thread. This thread runs in the background, and anytime a component needs to be painted, the paint method for the corresponding Graphics object is called. It is important to note from this that we do not typically call the paint method directly. Instead, the method will be called automatically when it is required. This can occur in many different cases, such as when the window is resized, or when a new component is made visible.

Drawing Basic Shapes

Java has a set of built-in functions for drawing simple shapes to the screen. We will start by looking at how we can use the paint method to draw an oval on the screen. To start, we can set up a typical Swing JFrame to display our graphics.

public class Oval extends JFrame {

    public static void main(String[] args) {
        Oval drawing = new Oval();
        drawing.setVisible(true);
    }

    public Oval() {
        super("Oval Picture");

        setSize(500, 500);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        getContentPane().setBackground(Color.white);
    }
}

To draw the oval, first, we will define the paint method within the Oval class. Once this is completed, we can add the code to paint what is required to the screen:

public void paint(Graphics g) {
    super.paint(g);
    g.drawOval(250, 250, 50, 50);
}

The line super.paint(g); takes care of painting any GUI components that are not custom graphics. Once this is completed, we add a line to paint our oval to the screen. The drawOval method takes in four arguments. The first two specify the x and y coordinate that the upper left corner of the bounding rectangle for the oval. The next two specify the width and height of the oval. The result of this code is an unfilled oval being drawn to the coordinates (250,250) on the screen, with a width and height of 50.

When using the drawOval method, Java will draw an unfilled oval to the screen, meaning the center is the same color as the background. If you want to specify a color for the oval, there are a few minor adjustments required.

public void paint(Graphics g) {
    super.paint(g);
    g.setColor(Color.BLUE);
    g.fillOval(250, 250, 50, 50);
}

This code sets the graphic color to blue, then calls fillOval instead of drawOval. The result is that we get an oval with a blue center drawn to the screen.

There are plenty of other shapes that can be drawn with the graphics class. To demonstrate a few more, take a look at the paint function below.

public void paint(Graphics g) {
    super.paint(g);
    g.setColor(Color.BLUE);

    g.fillOval(250, 250, 50, 50);
    g.drawOval(50, 50, 50, 50);

    g.drawLine(100, 70, 200, 200);

    g.drawRect(300, 300, 100, 100);
    g.fillRect(50, 300, 100, 100);
}

The drawLine method is able to draw a line between two points. The first two arguments represent the x and y coordinates of the first point, and the last two arguments are the x and y coordinates of the second point. The drawRect and fillRect methods follow a similar idea to the drawOval and fillOval methods. They draw a rectangle at the x and y coordinates provided, with a given width and height.

The Repaint Method

There are some instances where we may want to force the Swing GUI to run the paint method again. For instance, if we draw a shape based on a user event, we would want to repaint the screen when the user event occurs. In order to do this, Java implements a special method called repaint which is used to trigger a call to the paint method.

As an example, let’s try creating a button that draws a rectangle on the screen. The idea of the code will be that we set up a boolean that keeps track of if the button has been pressed or not. Once the button is pressed, we set the boolean to true, and call repaint. Within the paint function, we check if the boolean is true, and if it is, we paint the rectangle to the screen.

public class Oval extends JFrame {
    private boolean drawShape;

    private class ShapeAction implements ActionListener {
        public void actionPerformed(ActionEvent e) {
            drawShape = true;
            repaint();
        }
    }

    public static void main(String[] args) {
        Oval drawing = new Oval();
        drawing.setVisible(true);
    }

    public Oval() {
        super("Oval Picture");
        setSize(500, 500);

        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setLayout(new BorderLayout());
        getContentPane().setBackground(Color.white);

        JButton shapeButton = new JButton("Click for a square");
        shapeButton.addActionListener(new ShapeAction());
        add(shapeButton,BorderLayout.SOUTH);

        drawShape = false;
    }

    public void paint(Graphics g) {
        super.paint(g);
    
        if (drawShape) {
            g.drawRect(250, 250, 100, 100);
        }
    }
}

Notice that when the button is pressed, the repaint method is called. This will cause Java to add a new instance of the paint method to the Event Dispatch Thread. When the paint method is run, it will see that drawShape is true, and draw the rectangle to the screen. With this sort of logic, we can easily update our interfaces whenever an update is required.

Moving Shapes

One application of the repaint method is giving a user the ability to click and drag graphics around the screen. To implement this functionality, we can use a MouseMotionListener to determine where the mouse currently is, and update our graphic position. To demonstrate this, let’s try drawing a rectangle, and allowing the user to drag it around the screen.

To keep track of the location we want to draw the rectangle at, we can use two private variables to track the x and y coordinate. When the user drags their mouse on the screen, we can update these two variables to the position of the mouse. The overall set up of the Swing project is similar to our other examples, with the addition of implements MouseMotionListener to allow us to use methods related to the user mouse position.

public class Oval extends JFrame implements MouseMotionListener {
    private int rectX = 50;
    private int rectY = 50;

    public static void main(String[] args) {
        Oval drawing = new Oval();
        drawing.setVisible(true);
    }

    public Oval() {
        super("Oval Picture");
        setSize(500, 500);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        getContentPane().setBackground(Color.white);
        addMouseMotionListener(this);
    }

    public void paint(Graphics g) {
        super.paint(g);
        g.drawRect(rectX, rectY, 50, 50);
    }
}

To update the position of the rectangle, we can use the mouseDragged method, which tells us the x and y coordinates of the mouse for as long as the mouse is being dragged. In this method, we can update the rectangle coordinates, and call repaint to draw the new rectangle.

@Override
public void mouseDragged(MouseEvent e) {
    rectX = e.getX();
    rectY = e.getY();
    repaint();
}

@Override 
public void mouseMoved(MouseEvent e) { }

With this code, we now have a fully functional application that allows for the user to click and drag graphics around the screen.

Leave a Reply

Your email address will not be published.