2

This code runs just the window frames but I can't get the small blue filled rectangles to display. Why is that? The code looks logical to me.

I am trying to create 2 JFrame windows with a blue rectangle in each.

public class ColoredRectangle {
    // attributes of the rectangle
    int width = 40;
    int height =20;
    int x = 80;
    int y = 90;
    JFrame window = new JFrame("Box Run");
    Color color =  Color.BLUE;

    // the construtor of the window
    public ColoredRectangle() {
        window.setSize(200,200);
        window.setVisible(true);
    }

    //the actual rectangle
    public void paint () {  
        Graphics g = window.getGraphics();
        g.setColor(color);
        g.fillRect(x, y, width, height);
    }

    public static void main(String[] args) throws IOException {
        // creating 2 windows
        ColoredRectangle r1 = new ColoredRectangle();
        ColoredRectangle r2 = new ColoredRectangle();

        //drawing a blue rectangle in each window
        r1.paint();
        r2.paint();
    }
}
CDspace
  • 2,639
  • 18
  • 30
  • 36
appletree
  • 57
  • 6

1 Answers1

3

As per comments made:

  • Override paintComponent not paint
  • Always call the super's paint method in your override. This is critical when you try to do animation (something you're sure to do next). The super's call will clean any dirty pixels.
  • paintComponent should be protected, not public.
  • The Swing GUI should be created on the event thread by passing a Runnable into the SwingUtilities.invokeLater(...) method.
  • Don't use a Graphics object obtained by calling getGraphics() on a Swing component (with a few exceptions). The object obtained this way will not persist or be stable, risking a disappearing image or worse, a NullPointerException. Instead Swing graphics are generally done passively by drawing within a painting method, and allowing the JVM to call this method when and where needed. This will require a paradigm shift when drawing animations.

For example:

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;

import javax.swing.*;

@SuppressWarnings("serial")
public class DrawRectPanel extends JPanel {

    private static final int PREF_W = 200;
    private static final int PREF_H = PREF_W;
    private Color RECT_COLOR = Color.BLUE;
    private static final int RECT_X = 80;
    private static final int RECT_Y = 90;
    private static final int RECT_W = 40;
    private static final int RECT_H = 20;

    public DrawRectPanel() {
        setPreferredSize(new Dimension(PREF_W, PREF_H));
    }

    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);
        g.setColor(RECT_COLOR);
        g.fillRect(RECT_X, RECT_Y, RECT_W, RECT_H);
    }

    private static void createAndShowGui() {
        JFrame frame = new JFrame("DrawRectPanel");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.getContentPane().add(new DrawRectPanel());
        frame.pack();
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(() -> createAndShowGui());
    }
}

Edit: to create 2 JFrames, change the GUI like so:

private static void createAndShowGui() {
    JFrame frame = new JFrame("DrawRectPanel");
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.getContentPane().add(new DrawRectPanel());
    frame.pack();
    frame.setLocationByPlatform(true);
    frame.setVisible(true);
}

public static void main(String[] args) {
    SwingUtilities.invokeLater(() -> {
        createAndShowGui();
        createAndShowGui();
    });
}

By setting the JFrame's location "by platform" you let the OS position it where it sees fit to do so, although I must also print a link to this related StackOverflow link: The Use of Multiple JFrames: Good or Bad Practice?

Hovercraft Full Of Eels
  • 283,665
  • 25
  • 256
  • 373