i am adding graphic class object "g" in JFrame class in Netbeans. but error are occurring as
"non static variable g can not be referenced from a static context"
following are code of graphic class (just drawing a rectangle)
public class grafix extends JComponent {
#Override
public void paintComponent(Graphics g){
Graphics2D g2= (Graphics2D) (Graphics) g;
Rectangle r = new Rectangle(15,10,200,300);
g2.draw(r);
}
}
and
following are object adding line in Main() of JFrame class.
new JFrame().getContentPane().add(g);
object "g" been declared in JFrame class. Since i am using Netbean that why i have to use getContentPane().add() instead of JFrame.add();
Related
I am quite new to Java application development and I want to draw some simple shapes in the JFrame-canvas without using one main class but rather split it into a main class and a class playerRectangle. In the playerRectangle class I created a method paint:
public void paint(Graphics g) {
setSize(500, 500);
g.drawRect(320, 20, 640, 120);
}
I then created an object in some render funtion in the main class and called the paint function of this object.
playerRectangle p1 = new playerRectangle();
p1.paint(null);
But somehow it threw the java.lang.NullPointerException error and didn't render the rect to the screen. When I don't split this function into two classes it works properly even though it throws this error. So please help me and tell me, what I am missing here.
Any research on Youtube and other stuff only told me that I have to create classes like screen etc. but I am not so sure that is helping me.
Thanks for helping
Simple example how to draw Rectangle using standard libraries :
public class SomeClass extends JPanel {
public void paintComponent(Graphics g) {
super.paintComponent(g);
g.setColor(Color.GREEN);
g.fillRect(0,0,320,220);
}
SomeClass() {
JFrame frame = new JFrame();
frame.serContentPane(this);
frame.setBounds(0,0,320,220);
frame.setVisible(true);
}
}
Class with main method:
public class Main {
public static void main(String[] args) {
new SomeClass();
}
}
I ran into a problem where no matter what I do my JPanel won't repaint. I was using the following method to create a connect four game board and dynamically change the color of the circles as the play progresses, but I've simplified it into a test class which has the same issue.
I decided to use a state pattern design for each of the circles. The following is the code for the classes so it knows which color to print which are JPanel children classes.
public class GridCircle extends JPanel
{
public void paintComponent(Graphics g)
{
super.paintComponent(g);
g.setColor(Color.BLUE);
g.fillRect(0, 0, 100, 100);
}
}
public class WhiteGridCircle extends GridCircle
{
public void paintComponent(Graphics g)
{
super.paintComponent(g);
g.setColor(Color.WHITE);
g.fillOval(5, 5, 80, 80);
}
}
public class RedGridCircle extends GridCircle
{
public void paintComponent(Graphics g)
{
super.paintComponent(g);
g.setColor(Color.RED);
g.fillOval(5, 5, 80, 80);
}
}
The following is a test class where I attempt to change the class of a JPanel in the main method to see if it would change the color that is painted (which fails).
public class test extends JFrame
{
static JPanel testPanel = new WhiteGridCircle();
public static void main(String[] args)
{
new test();
testPanel = new RedGridCircle();
testPanel.revalidate();
testPanel.repaint();
}
test()
{
this.add(testPanel);
this.setSize(150,150);
this.setDefaultCloseOperation(EXIT_ON_CLOSE);
this.setVisible(true);
}
}
I can't figure out why the panel wouldn't repaint no matter what I've tried. From what I understand repaint() has no guarantee to call a the paint method but I see no reason it shouldn't when theres nothing else going on.
Because instance you created and added this.add(testPanel); is still new WhiteGridCircle().
You changed instance but the original one added to JFrame remains in the frame.
To change call this.getContentPane().add(testPanel); after instantiating RedGridCircle and before revalidate() call.
Im making a game but I have found a problem. Lets say I had 2 classes 1 With JPanel/JFrame and its paintComponenet in it. That will draw the graphics onto the frame. And the other called MainMenu.java only has a Rectangle Object in it:
Rectangle r = new Rectangle();
And In that class I set properties to it:
r.setSize(100, 200)
How would I send it I know how to draw objects.
Question: How do I take a graphics object from another class and take it to the class with paint on it and draw it but keep its properties?
How do I take a graphics object from another class and take it to the class with paint on it and draw it but keep its properties?
You don't. Everything should be drawn within the graphics context of the paintComponent method.
One solution is to keep a List<Rectangle> in the panel class you are drawing on and iterate through the list the draw the objects. Have a method in the class to add shapes to it
public class DrawingPanel extends JPanel {
private List<Rectangle> rects = new ArrayList<Rectangle>();
protected void paintComponent(Grapchics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D)g;
for (Rectangle rect: rects) {
// draw rectangle
}
}
public void addRectangle(Rectangle rect) {
rects.add(rect);
repaint();
}
}
Now you can do something like
DrawingPanel panel = new DrawingPanel();
Rectangle rect = new Rectangle(...);
panel.addRectagnle(rect);
Every new rectangle you add will be painted on the panel. You can initialize the list with no rectangle, and nothing will be painted until you add one.
I need to draw a square,line,circle when pressed the corespondent button. Also I need to do this using FactoryMethod design pattern.
I simply don't get how to draw on the same canvas, and because I have a class for every shape, how do i get the corresponding paint(Graphics g) method?
This is what I have so far:
public interface Shape
{
public void draw();
}
Square class
public class Square extends Canvas implements Shape
{
Graphics g;
Canvas c;
public Canvas getCanvas()
{
return c;
}
public void setCanvas(Canvas c)
{
this.c=c;
}
#Override
public void draw()
{
g.drawRect(20, 30,100,100);
}
public void paint(Graphics g)
{
g.drawRect(20, 30,100,100);
g.setColor(Color.BLUE);
}
}
Factory
public class ClassFactory extends Canvas{
JButton patrat;
Figura d;
String nameButon;
Graphics g;
Canvas c;
public Canvas getCanvas()
{
return c;
}
public void setCanvas(Canvas c)
{
this.c=c;
}
public ClassFactory()
{
super();
this.setBounds(0,0,500,450);
this.setBackground(Color.CYAN);
JButton square=new JButton("square");
patrat.setBounds(510, 10, 80,25);
JPanel panel=new JPanel();
panel.setLayout(null);
panel.setBounds(0,0,600,500);
panel.setBackground(Color.GRAY);
panel.add(this);
this.addComponentListener(p);
panel.add(square);
JFrame f=new JFrame("Draw");
f.setLayout(null);
f.setBounds(50,50,700,600);
f.getContentPane().setBackground(Color.DARK_GRAY);
f.setResizable(false);
f.add(panel);
f.show();
}
public Shape getFigure()
{
Shape d=null;
if(nameButton.equals("square"))
{
d=new Square();
}
return d;
}
}
Suggestions:
The factory should not create a GUI, should not extend Canvas, or really extend anything, it should not create a JFrame or do anything of the sort. It should concern itself only with creating objects of Shape child classes. The GUI creation code should be elsewhere.
Likely the factory's getFigure(...) method will be the one to produce this. It should likely accept a parameter, perhaps a String or an enum, that tells it what sub-class of Shape to produce.
Shape's draw method should likely accept a Graphics parameter so that its children can use it to draw with.
You shouldn't mix AWT components (i.e., Canvas) and Swing components together unnecessarily. Instead, just draw in a JPanel's paintComponent(Graphics g) method, not in a Canvas's paint(Graphics g) method.
In that JPanel have a Shape variable that is not initialized, perhaps called shape.
Inside of paintComponent(...) check if shape is null. If not, draw it by calling shape.draw(g).
In your JButton ActionListeners, have the Factory create a Shape child class object and assign it to the shape variable
Then call repaint() on the JPanel that does the drawing.
public class MyDrawPanel extends JPanel {
public void paintComponent(Graphics g){
Graphics2D gd2 = (Graphics2D) g;
GradientPaint gradient = new GradientPaint(70,70,Color.blue,150,150,Color.red);
}
}
Why is this valid but not this:
public class MyDrawPanel extends JPanel {
public void paintComponent(Graphics2D g){
GradientPaint gradient = new GradientPaint(70,70,Color.blue,150,150,Color.red);
g.setPaint(gradient);
g.fillOval(70,70,100,100);
}
}
First one renders, but the second one renders no graphics other than the frame. I noticed that paintComponent() requires a Graphics object, but if Graphics2D is a subclass of the Graphics object why can I not call a subclass of Graphics?
Is there some concept I am not picking up as to why this is?
It says that you should implement it this way, because Graphics2D is Graphics, while Graphics is not Graphics2D.
If you find casting disturbing, you can always create your own eg. MyJPanel that extends JPanel, define your own method, and subclass it in the future, overriding your defined method.
public class MyJPanel extends JPanel {
#Override
protected void paintComponent(Graphics g) {
paintComponent((Graphics2D) g);
}
protected void paintComponent(Graphics2D g) {
}
}
Basically, when you override a method, you can be equally or less specific.
Think about this:
JPanel p = new MyPanel();
p.paintComponent(someGraphicsInstance);
A reference to a JPanel is expected to be able to accept a Graphics reference as a parameter to the paintComponent method. Your method, however, violates that requirement as it will not accept a Graphics instance, but only a Graphics2D.
More information about this can be found https://stackoverflow.com/a/9950538/567864