1

I'm making a game in which the screen needs to be updated after a set of procedures (not continuously every frame) and I made a smaller program to test Graphics2D drawing. In this program, all I wanted to do was draw a small rectangle in the corner. However, the rectangle doesn't appear to draw. I'm not sure if I'm misunderstanding the use of BufferStrategy (i.e. there's a better way to update the game in this manner), but I tried calling the draw method twice to make sure the graphics2D object exists and is not null.

import java.awt.Canvas;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.image.BufferStrategy;
import javax.swing.*;

public class test extends Canvas
{
    private JFrame testWindow = new JFrame("Test");

    public test()
    {
        createUI();
    }

    public static void main(String[] args)
    {
        new test();
    }

    public void createUI()
    {
        testWindow.setSize(500,500);
        testWindow.setLayout(null);
        testWindow.setLocationRelativeTo(null);
        testWindow.setResizable(false);
        testWindow.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        testWindow.add(this);

        testWindow.setVisible(true);

        draw();
        draw();
    }

    public void draw()
    {
        BufferStrategy bs = this.getBufferStrategy();
        System.out.println(bs); 
        //when the program runs this prints null once and then an identifier
        if(bs == null)
        {
            this.createBufferStrategy(3);
            return;
        }

        Graphics g = bs.getDrawGraphics();
        Graphics2D g2 = (Graphics2D) g;

        g2.setColor(Color.RED);
        g2.fillRect(10,10,100,100);

        g2.dispose();
        bs.show();
    }
}
Bobulous
  • 12,967
  • 4
  • 37
  • 68
lumpman2
  • 23
  • 4
  • I recommend you take a look at this Java Swing tutorial [Performing Custom Painting](https://docs.oracle.com/javase/tutorial/uiswing/painting/index.html). – Bobulous Jul 23 '18 at 20:15

1 Answers1

3

The Good

Most of you code is pretty close to getting what you're trying to accomplish. It's just that the organization is a little off and your creation of class instances is a little messy.

The Bad

In general it is good to refrain from mixing Java Swing elements (JFrames) with AWT elements (Canvas). And I don't really know what your motivation is behind using BufferStrategy. Also, dealing with Java Swing components and their weird sporadic calls to paintComponent can be a pain for game development.

The Ugly

You're probably going to have to switch over to Swing and use threads, as it would be a cleaner solution. And if the game you are making is going to be even relatively graphics intensive, you will want to use OpenGL or better yet, a wrapper library over OpenGL, like LWJGL or my favorite, LibGDX.

But for the time being, here is a working example like the one you were trying to make using Oracle's Custom Painting Tutorial:

import javax.swing.SwingUtilities;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.BorderFactory;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;

public class Test {
    private static JFrame testWindow;

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

    private static void createUI() {
        testWindow = new JFrame("Test");
        testWindow.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        testWindow.add(new MyPanel());
        testWindow.pack();
        testWindow.setVisible(true);

    }
}

class MyPanel extends JPanel {

    public MyPanel() {
        setBorder(BorderFactory.createLineBorder(Color.black));
    }

    public Dimension getPreferredSize() {
        return new Dimension(500,500);
    }

    public void paintComponent(Graphics g) {     
        super.paintComponent(g);       
        Graphics2D g2 = (Graphics2D) g;

        g2.setColor(Color.RED);
        g2.fillRect(10,10,100,100);

        g2.dispose();
    }  
}

Let me know if you have any questions.

Note: Class names should always be capitalized.

agillgilla
  • 859
  • 1
  • 7
  • 22
  • I have a couple questions so I can understand this better: 1) When exactly is the paintComponent method called, and what is the purpose of using super.paintComponent? 2) How does using the Runnable interface work in what makes it necessary in this instance? – lumpman2 Jul 23 '18 at 21:58
  • All of those questions have been asked on SO already. Instead of answering them in a comment I'll give you the links: 1) [When is paintComponent called](https://stackoverflow.com/questions/15544549/how-does-paintcomponent-work), [Why call super.paintComponent](https://stackoverflow.com/questions/28724609/what-does-super-paintcomponentg-do) 2) [Java Swing invokeLater (for runnable)](https://stackoverflow.com/questions/6567870/what-does-swingutilities-invokelater-do) – agillgilla Jul 23 '18 at 22:10