0

I tried few source codes of drawing in java and they were working fine, but when i tried to make one of my own I could not get the paint(Grahpics g) method to work! I looked again at the codes I have and checked some of the tutorials in Oracle's pages but i don't seem to be able to know why it would not work. can someone please check it and tell me what is wrong here??

main method: public class main

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

board:

import java.awt.BorderLayout;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;

import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.Timer;


public class board implements ActionListener
{
    private JFrame f = new JFrame("Speedy");
    private JPanel gamePanel = new JPanel();


    private Image bg = new ImageIcon(this.getClass().getResource("road.png")).getImage();
    private Timer t;


    private car myCar = new car();


    public board()
    {
        t = new Timer(50,this);
        t.start();


        gamePanel.setSize(600,400);
        gamePanel.setDoubleBuffered(true);
        gamePanel.setFocusable(true);
        gamePanel.addKeyListener(new TAdapter());

        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        f.add(gamePanel,BorderLayout.CENTER);
        //f.addKeyListener(new TAdapter());
        f.setBounds(200,100,600,400);
        f.setVisible(true);
        f.revalidate();
        f.repaint();

    }




    public void paint(Graphics g) {
        gamePanel.paint(g);

        Graphics2D g2d = (Graphics2D)g;
        g2d.drawImage(bg,0,0,null);
        g2d.drawImage(myCar.getImg(), myCar.xPos, myCar.yPos, null);

        System.out.println("Painted");

        g.dispose();
    }



    public void actionPerformed(ActionEvent e) 
    {
        gamePanel.repaint();
        //System.out.println("Painting..");
    }





    private class TAdapter extends KeyAdapter {

        public void keyReleased(KeyEvent e) {}

        public void keyPressed(KeyEvent e)  
        {
            myCar.keyPressed(e);
            System.out.println("You pressed: "+e);
        }
    }

}

car.java:

    import java.awt.Image;
    import java.awt.event.KeyEvent;
    import java.util.ArrayList;

    import javax.swing.ImageIcon

;



public class car 
{

    private Image image;
    public int xPos,yPos;

    public car()
    {
        image = new ImageIcon(this.getClass().getResource("car.png")).getImage();
        xPos = 300;
        yPos = 200;
        System.out.println(image.getWidth(null));
    }



    public Image getImg() {return image;}


    public void move() {}


    public void keyPressed(KeyEvent e) 
    {

        int key = e.getKeyCode();

        if (key == KeyEvent.VK_LEFT) xPos -= 1;
        if (key == KeyEvent.VK_RIGHT)xPos += 1;
        if (key == KeyEvent.VK_UP)   yPos -= 1;
        if (key == KeyEvent.VK_DOWN) yPos += 1;
    }

}

There are no errors, it shows me the width of the image which is right, also the timer triggers the ActionListener, also KeyListener is working, but the images would not draw! the paint(Graphics g) method just does not want to get triggered! Googling it did not help.. I thought this would be a common problem but nobody has the problem I have, all solutions failed me. help please? If someone can explain it would be most appreciated!

bakz
  • 79
  • 15

3 Answers3

0

Your class Board does not extend the JPanel class. So the paint() method is never called by the Swing. Also, the statement gamePanel.repaint() will only execute the default JPanel paint() method of gamePanel. Instead you want the overridden paint method to be executed, so might want to do this:

public class Board extends JPanel implements ActionListener {
   ....
    public void paint(Graphics g) {
       this.paint(g);

       Graphics2D g2d = (Graphics2D)g;
       g2d.drawImage(bg,0,0,null);
       g2d.drawImage(myCar.getImg(), myCar.xPos, myCar.yPos, null);

       System.out.println("Painted");

       g2d.dispose();
    }
    ....
}

Replace your action functionality with this:

public void actionPerformed(ActionEvent e) {
   this.repaint();
}

Alternative solution: If you do not want your Board class to extend JPanel, you can also override the paint() method of the gamePanel as you initialize it.

gamePanel = new JPanel() {
   @Override
   public void paint(Graphics g) {
       this.paint(g);

       Graphics2D g2d = (Graphics2D)g;
       g2d.drawImage(bg,0,0,null);
       g2d.drawImage(myCar.getImg(), myCar.xPos, myCar.yPos, null);

       g2d.dispose();
   }
};

However, I would recommend the first solution rather than this one with anonymous classes.

vsimkus
  • 335
  • 1
  • 10
  • but i did `gamePanel.repaint()`, shouldn't that trigger it? can't i trigger it onto the current JPanel? – bakz Mar 06 '16 at 13:24
  • No, `gamePanel` is an instance of a `JPanel`, calling `gamePanel.repaint()` is only going to trigger the original `JPanel` `paint()` method. However, you want to trigger **your** `paint` method which has the implementation of drawing a car. I have updated my answer. – vsimkus Mar 06 '16 at 13:27
  • Is it possible to set the current paint method for the new instance of the JPanel in the current code? or do i have to create a new object of it? – bakz Mar 06 '16 at 13:30
  • also, based on what you are saying the `paint(Graphics g)` method is actually an override of the original `JPanel` object? – bakz Mar 06 '16 at 13:34
  • Yes, you could override the `paint` method of the `gamePanel` when you initialize it. Regarding your second question, the `paint` method is supposed override the default `paint` method in order to extend the default functionality. – vsimkus Mar 06 '16 at 13:38
  • I really appreciate your help, I'd give you a +1 but not enough reputation yet :( thank you very much, it makes more sense now – bakz Mar 06 '16 at 13:40
  • No problem, I'm glad I could help! – vsimkus Mar 06 '16 at 13:44
0

When you call repaint on some container, then what happens is that Swing looks at all the components in that container and calls their paint method.

However, your board class (you should be calling it Board, by the way. Class names should always start with a capital) is not a component of your JFrame. When you call repaint, Swing will attempt to call the paint method of the JPanel that is a component of that JFrame. But you didn't override that method. You just added a paint method to your board, and board is not a component of the JFrame.

For this reason, usually you are supposed to create a class that extnds JPanel or some other component, and then add the current object of that class as a component to the JFrame. This way, your paint method will be called when the JFrame is repainted.

RealSkeptic
  • 33,993
  • 7
  • 53
  • 79
0

Your "main" class (board) should extend JPanel to work as expected. With your way, paint would never be called. it acts like any normal self-written function.

If you want to keep things as they are, you can do something ike that:

gamePanel = new JPanel() 
{
    @Override
    public void paint(Graphics g) 
    {
        //your code here
    }
};

Please keep in mind that a Class name should start with a capital letter. It won't make any errors but it is a naming convention as you can see here: http://www.oracle.com/technetwork/java/codeconventions-135099.html