I feel like I went through everything I needed to do:
Make a graphics class that has a void called paintComponent and extends JComponent
Have that paintComponent void have Graphics g as a parameter, then do Graphics2D g2d = (Graphics2D) g;
Add the Graphics class to my JFrame
I can't find anything wrong with this, so I'm a little confused.
My code is here:
public static void main(String[] args) {
DragonEscape game = new DragonEscape();
frame.setTitle(title);
frame.setSize(1000, 500);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
frame.setResizable(false);
frame.setLocationRelativeTo(null);
frame.add(new Graphicsa());
frame.add(game);
}
and
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import javax.swing.JComponent;
public class Graphicsa extends JComponent {
private static final long serialVersionUID = 1L;
public Graphics g;
protected void paintComponent(Graphics g) {
Graphics2D g2d = (Graphics2D) g;
g.fillRect(0, 0, 1000, 500);
g.setColor(Color.gray);
g.fillRect(0, 0, 100, 100);
}
}
frame.add(new Graphicsa());
frame.add(game);
Only one component can be added to the CENTER of the BorderLayout of the JFrame. So your game component replaces the graphics component.
Read the Swing tutorial for Swing basics. There are sections on:
How to use BorderLayout
Custom Painting
that directly related to this question.
Also, why are you even trying to do graphics painting? If looks to me like you are just trying to paint the background a certain color. Just use the setBackground(...) method on your game component.
Related
My paintComponent() won't get called.
I have Googled a little, and haven't found an answer that I could use. At first, I didn't have the frame.getContentPane().add(this), and thought that the answer was to insert that, but neither that worked. I hope someone can help me out.
Here you have a little snippet of my code:
package engine;
import java.awt.Graphics;
import java.awt.Graphics2D;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class Frame extends JPanel {
private static final long serialVersionUID = 1L;
private JFrame frame = new JFrame();
private GameEngine engine;
private Game game;
public Frame(GameEngine engine) {
this.engine = engine;
frame.setExtendedState(JFrame.MAXIMIZED_BOTH);
frame.setUndecorated(true);
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(null);
frame.setSize(1920, 1080);
frame.getContentPane().add(this);
}
public void updateGame(Game game) {
this.game = game;
}
public JFrame getFrame() {
return frame;
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g;
g2d.drawString("" + game.getClockDate(), 1920 - 100, 20);
System.out.println("test");
}
}
I'm calling it from here, in another class:
public void loop() {
if (this.ingame) {
game.loop();
frame.updateGame(game);
frame.repaint();
}
}
Try calling super() as the first line of your constructor so that your JPanel initializes correctly.
public Frame(GameEngine engine) {
super();
this.engine = engine;
frame.setExtendedState(JFrame.MAXIMIZED_BOTH);
frame.setUndecorated(true);
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(null);
frame.setSize(1920, 1080);
frame.getContentPane().add(this);
}
Also call the #Override annotation for getting your code clear.
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g;
g2d.drawString("" + game.getClockDate(), 1920 - 100, 20);
System.out.println("test");
}
Please post what context you are trying to paint this Frame object (where, when, and how you are using the paint method in your Frame object).
General diagnostic resources:
1. Inheritance Hierarchy
2. This post has a very good position on why not to use paintComponent() and to use repaint() instead. I have never been put into a situation where I have needed to forge a path with paintComponent(), however I have been in a position to use repaint() several times.
You are calling repaint in the game loop, but repaint does not guarantee that window will be repainted and therefore paintComponent may not be called. You should instead use paintImmediately.
paintImmediately(0, 0, 1920, 1080);
I am new to Java and I have a problem with drawing an oval using paintComponent method. I found many similar threads, but none of the soultions worked. My code:
RacerMain.java
import javax.swing.*;
import java.awt.*;
public class RacerMain {
public static void main (String[]args) {
//MainFrame mf = new MainFrame();
JFrame jframe = new JFrame();
JPanel jpanel = new JPanel();
jframe.setSize(480,640);
jframe.add(jpanel);
jframe.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
jpanel.add(new Dot());
jframe.setVisible(true);
}
}
Dot.java
import java.awt.*;
import javax.swing.*;
public class Dot extends JComponent{
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D)g;
g2d.setColor(Color.BLUE);
g2d.fillOval(20, 20, 20, 20);
}
}
Why it does not work and how to get this code working?
JPanel uses FlowLayout which respects preferred sizes but the default size of the Dot component is too small to be seen. You need to use a layout manager that uses the maximum area available or override getPreferredSize. Remember to call pack before calling JFrame#setVisible
jpanel.setLayout(new BorderLayout());
Or you can set preferred size in constructor:
import java.awt.*;
import javax.swing.*;
public class Dot extends JComponent {
public Dot() {
setPreferredSize(new Dimension(480, 640));
}
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g;
g2d.setColor(Color.BLUE);
g2d.fillOval(20, 20, 20, 20);
}
}
How can I draw a circle that is resizable when the window is maximized or minimized? The code I have isn't really even draw the circle like I would like it to either. Any help with this would be greatly appreciated as I have never worked with graphics in Java before and the Oracle site is only helping me so much. Thanks.
public class GUI extends JFrame {
public GUI() {
JPanel p1 = new JPanel();
}
public void paintComponent(Graphics g) {
Graphics2D g2d = (Graphics2D) g;
g2d.drawOval(0, 0, 50, 50);
}
public static void main(String[] args) {
GUI frame = new GUI();
frame.setTitle("Circle Generator");
frame.setSize(400, 300);
frame.setLocationRelativeTo(null); // Center the frame
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
To make the painting dynamic you need to get the current width/height of the panel.
public void paintComponent(Graphics g)
{
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g;
//g2d.drawOval(0, 0, 50, 50);
g2d.drawOval(0, 0, getWidth(), getHeight());
}
You also need the super.paintComponent(g) to clear the background of the panel.
Edit:
Actually, I took a closer look at your code and it does nothing. A JFrame does not have a paintComponent() method so your code will never be executed. Also, you create a panel but then don't do anything with it.
Start by reading the section from the Swing tutorial on Custom Painting for more information and working examples.
Then you can modify the example from the tutorial to draw your oval, using the suggestion give above.
I am currently working on a project, I get this error Java.lang.NullPointerException, I undrestand that this error happen when you try to refer to a null object instance, but what I do not know, is how I can fix it.
This is my code:
public void paint(Graphics g) {
g.setColor(Color.red);
g.drawOval(150, 150, 10, 10);
}
/** Main Method **/
public static void main(String [] args) {
Run run = new Run();
run.paint(null);
}
Please help me with a solution and also explain it, so that I learn it. Many thanks in advance. Andre
You may not pass null to your paint method! Here is a small example how to do it:
import java.awt.Graphics;
import javax.swing.JComponent;
import javax.swing.JFrame;
class MyCanvas extends JComponent {
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawOval (10, 10, 200, 200);
}
}
public class DrawOval {
public static void main(String[] a) {
JFrame window = new JFrame();
window.setBounds(30, 30, 300, 300);
window.getContentPane().add(new MyCanvas());
window.setVisible(true);
}
}
You almost never call paint methods (including paintComponent) directly as this is what the JVM should be doing.
Don't override the paint(Graphics g) method of a JComponent or JComponent derived class such as a JPanel if you can avoid it. This method, paint, is responsible for not only painting the component but also its borders and its child components, and if not done carefully, overriding this method will not infrequently result in unwanted side effects.
Later when you want to do graphics animation, overriding paint(Graphics g) will result in jerky graphics since it does not do double buffering by default.
By overriding the paintComponent(Graphics g) method instead you fix these issues.
Don't forget to call the super's paintComponent(g) method in your override to erase any unwanted previously drawn images.
Read the Swing Graphics tutorials, both the basic and advanced tutorials. Links at the bottom.
Better code:
import java.awt.Dimension;
import java.awt.Graphics;
import javax.swing.JComponent;
import javax.swing.JFrame;
#SuppressWarnings("serial")
public class MyBetterCanvas extends JComponent {
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawOval(10, 10, 200, 200);
}
public static void main(String[] a) {
MyBetterCanvas canvas = new MyBetterCanvas();
canvas.setPreferredSize(new Dimension(300, 300));
JFrame window = new JFrame("My Better Canvas");
window.getContentPane().add(canvas);
window.setLocationByPlatform(true);
window.pack();
window.setVisible(true);
}
}
Better Still:
import java.awt.Color;
import java.awt.Dimension;
import java.awt.GradientPaint;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Paint;
import java.awt.RenderingHints;
import javax.swing.JComponent;
import javax.swing.JFrame;
#SuppressWarnings("serial")
public class MyBetterStillCanvas extends JComponent {
private static final int PREF_W = 500;
private static final int PREF_H = 500;
private static final int OVAL_X = 10;
private static final int OVAL_Y = OVAL_X;
private static final Paint BG_PAINT = new GradientPaint(0, 20,
Color.black, 20, 0, Color.darkGray, true);
private static final Paint FILL_PAINT = new GradientPaint(0, 0,
Color.blue, 20, 20, Color.red, true);
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
// to smooth out graphics
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
// let's draw something funky
g2.setPaint(BG_PAINT);
g2.fillRect(0, 0, getWidth(), getHeight());
g2.setPaint(FILL_PAINT);
// avoid use of "magic" numbers
g.fillOval(OVAL_X, OVAL_Y, getWidth() - 2 * OVAL_X, getHeight() - 2
* OVAL_Y);
}
// a cleaner way to set the preferred size of a component
#Override
public Dimension getPreferredSize() {
return new Dimension(PREF_W, PREF_H);
}
public static void main(String[] a) {
JFrame window = new JFrame("My Better Canvas");
window.getContentPane().add(new MyBetterStillCanvas());
window.setLocationByPlatform(true);
window.pack();
window.setVisible(true);
}
}
Which displays as:
Tutorials:
Java Tutorials, Really Big Index
Java Swing Tutorials
Basic Swing Graphics Tutorial: Lesson: Performing Custom Painting
More Advanced Graphics Article: Painting in AWT and Swing
You are not doing it the right way. In order to use graphics in java you need to build upon Swing/AWT components. Currently you are passing Graphics as null.
run.paint(null);
You need to implement this using JFrame and other swing components.
Since you are sending null to paint, Graphics g contains null (points to nowhere).
Then inside paint(...) you call setColor(...) on g, which is null. null.setColor(...) causes NullPointerException.
I have not used Swing/G2D much, so please be patient.
I have the following class which is a component on my GUI (meant to be a kind of Canvas to draw on):
import javax.swing.*;
import java.awt.*;
public class DrawPanel extends JComponent{
public void paintComponent(Graphics g){
Graphics2D g2 = (Graphics2D) g;
g2.setPaint(Color.black);
g2.fillRect(0, 0, getWidth(), getHeight());
BrushStroke bs = new BrushStroke();
add(bs);
}
}
I have been trying to add the following to the above JComponent:
import javax.swing.*;
import java.awt.*;
public class BrushStroke extends JComponent{
public void paintComponent(Graphics g){
Graphics2D g2 = (Graphics2D) g;
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
g2.setPaint(Color.red);
g2.fillOval(0, 0, 10, 10);
}
}
The BrushStroke does not show on the DrawPanel.
I have been searching forever for an answer, and each example I look at seems to be contradictory.
If anybody has attempted what I am, then help would be greatly appreciated. Also, if I am taking the completely wrong approach, please do say.
You should never add a component to a panel in any painting method. The painting methods are invoked whenever Swing determines a component needs to be painted. Therefore you would be adding the component to the panel multiple times.
When you do custom painting you are responsible for overriding the getPreferredSize() method to give the size of the component. This way the layout managers can position the components properly. If you don't do this then the preferred size is 0, so there is nothing to paint.
Read the section from the Swing tutorial on Custom Painting for more information and examples.
On the JComponent.add method, the documentation says:
Note: If a component has been added to a container that has been
displayed, validate must be called on that container to display the
new component. If multiple components are being added, you can improve
efficiency by calling validate only once, after all the components
have been added.
You should refresh your DrawPanel after adding an element to it. Watch out not to do it in the painComponent method, you will end up in an infinite recursion.
Do the following instead:
DrawPanel drawPanel = new DrawPanel();
drawPanel.add(new BrushStroke());
drawPanel.repaint();
EDIT
Here is a fully working solution (extending JPanels instead of JComponent)
public static void main(String[] args){
JFrame frame = new JFrame();
DrawPanel drawPanel = new DrawPanel();
drawPanel.add(new BrushStroke());
frame.getContentPane().add(drawPanel);
frame.pack();
frame.setVisible(true);
}
class DrawPanel extends JPanel{
public void paintComponent(Graphics g){
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
g2.setPaint(Color.black);
g2.fillRect(0, 0, getWidth(), getHeight());
}
#Override
public Dimension getPreferredSize(){
return new Dimension(100, 100);
}
}
class BrushStroke extends JPanel{
public void paintComponent(Graphics g){
this.setOpaque(false);
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2.setPaint(Color.red);
g2.fillOval(0, 0, 10, 10);
}
#Override
public Dimension getPreferredSize(){
return new Dimension(10, 10);
}
}
The output gives the following: