How to initialize a graphics g when building a RenderingEngine

460 Views Asked by At

So a buddy of mine built a RenderingEngine where it pretty much contains the methods that graphics has. That way you only need to call the RenderingEngines class's methods to render stuff to the screen. Without looking and trying to learn instead of cheating, im trying to replicate it based off my knowledge. I ran into a problem though. All my methods work its just that when the RenderingEngine class get initialized in my game class the graphics g in my RenderingEngine class is null after trying to get the JPanel's graphics. I don't know if i'm not understanding how this works and would love an explanation, ill put the code down below.

RENDERING CLASS BELOW:

package game.Main;

import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Rectangle;
import java.awt.font.FontRenderContext;
import java.awt.geom.AffineTransform;
import java.awt.image.BufferedImage;
import javax.swing.JPanel;


public class RenderingEngine extends JPanel
{
    private Graphics g;
    public RenderingEngine()
    {
        g = this.getGraphics();
    }

    public void setColor(Color color)
    {
        g.setColor(color);
    }

    public void fillRect(Rectangle rect)
    {
        g.fillRect(rect.x, rect.y, rect.width, rect.height);
    }

    public void drawRect(Rectangle rect)
    {
        g.drawRect(rect.x, rect.y, rect.width, rect.height);
    }

    public void setStringFont(Font font)
    {
        g.setFont(font);
    }

    public void drawString(String string, int x, int y)
    {
        g.drawString(string, x, y);
    }

    public void drawImage(BufferedImage image, Rectangle rect)
    {
        g.drawImage(image, rect.x, rect.y, rect.width, rect.height, this);
    }

    public void clear(Rectangle rect)
    {
        g.clearRect(rect.x, rect.y, rect.width, rect.height);
    }

    public int widthofString(String string, Font font)
    {
        String text = string;
        AffineTransform affinetransform = new AffineTransform();
        FontRenderContext frc = new FontRenderContext(affinetransform,true,true);
        Font f1 = font;
        int textwidth = (int)(font.getStringBounds(text, frc).getWidth());
        return textwidth;
        //int textheight = (int)(font.getStringBounds(text, frc).getHeight());
    }

    public int heightofString(String string, Font font)
    {
        String text = string;
        AffineTransform affinetransform = new AffineTransform();
        FontRenderContext frc = new FontRenderContext(affinetransform,true,true);
        Font f1 = font;
        //int textwidth = (int)(font.getStringBounds(text, frc).getWidth());
        int textheight = (int)(font.getStringBounds(text, frc).getHeight());
        return textheight;
    }

    public void paint()
    {

    }
}

WHERE I INITIALIZE RENDERINGENGINE IN THE GAME CLASS:

private void Load()
{
    frame = new JFrame();
    frame.setSize(800,600);
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.setLocationRelativeTo(null);
    frame.setResizable(false);
    render = new RenderingEngine();
    frame.add(render);
    LoadContent();
    gameloop = new GameLoop();
    gameloop.Run();
}
1

There are 1 best solutions below

6
Marco13 On

You might consider it as unsatisfactory when I answer the question about "How to initialize a Graphics g" for a JPanel with ...

Not at all!

You might want to have a look at the Performing Custom Painting article, or the article about Painting in AWT and Swing (which unfortunately was slightly messed up during the transition from Sun to Oracle, but still contains valuable and more detailed information than the other article).

The Graphics of a JPanel is, so to say, managed by the operating system, and represents an area on the screen where the painting may happen. When the panel is not yet visible, the Graphics that is returned by a call to getGraphics() may be null. It may also be null at other occasions. Particularly, when it is accessed from a thread that is not the event dispatch thread.

In general, as a rule of thumb:

Never call getGraphics on a Component!

One possible solution for such a "RenderingEngine" class would be to use the Graphics object of a BufferedImage. This should not be too complicated, but you'll have to consider several aspects here:

  • When will the image be initialized?
  • When will the graphics be initialized?
  • When will the graphics be disposed?
  • What happens when the panel is resized?
  • ...

However, with this method, it should at least be possible to create such a "RenderingEngine" that is suitable for the intended usage.