paintComponent method not being called by repaint

132 views Asked by At

I'm trying to call my paintComponent method by using repaint but it is never being called. This is my first class:

public class start
{
    public static void main(String[] args){
        Frame f = new Frame();
        f.createFrame();
    }
}  

And this is the class that I want the paintComponent method to be called to but all that happens is a blank frame appears:

import javax.swing.JButton;
import javax.swing.JComponent;
import java.awt.Graphics;
import javax.swing.JFrame;
import java.awt.image.*;
import javax.swing.Icon;
import javax.swing.ImageIcon;
import java.awt.event.*;
import java.awt.*;
import javax.swing.*;
import javax.swing.Timer;

public class Frame implements Runnable,ActionListener
{
JFrame window = new JFrame("Frame");
int i = 0;
Canvas myCanvas = new Canvas();
public void createFrame(){
    window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    window.setBounds(30, 30, 700, 500);
    window.setFocusable(true);
    window.setFocusTraversalKeysEnabled(false);
    window.setVisible(true);
    (new Thread(new Frame())).start();
}

public void run(){
    Timer timer = new Timer (17,this);
    timer.start();
}

public void actionPerformed(ActionEvent e){
    myCanvas.updateGame();
    myCanvas.render();
    window.add(myCanvas);
}
}

class Canvas extends JPanel{
int x = 10;
int y = 10;
public void updateGame(){
    x++;
}

public void render(){
    repaint();
    System.out.println("repaint");
}

@Override
protected void paintComponent(Graphics g){
    super.paintComponent(g);
    Graphics2D g2 = (Graphics2D) g;
    g.drawString("hi",x,y);
    System.out.println("paint");
}

}

Repaint is called multiple times but paint is never called. Why isn't the paintComponent method being called by repaint?

1

There are 1 answers

1
Amir Afghani On

Instead of creating a new frame, pass in the existing frame, I've commented the line below:

public void createFrame(){
    window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    window.setBounds(30, 30, 700, 500);
    window.setFocusable(true);
    window.setFocusTraversalKeysEnabled(false);
    window.setVisible(true);
    (new Thread(new Frame())).start(); <--- instead of creating a new frame, pass in the existing frame
}

You should really consider the following improvements as well:

1) Don't name your class Frame, as it collides with Frame

2) Move the body of createFrame as well as the following three lines:

JFrame window = new JFrame("Frame");
int i = 0;
Canvas myCanvas = new Canvas();

Into a constructor and make these local variables like Canvas into member fields.

3) Remove the last line that creates the thread out of the constructor, and expose it as a method (e.g 'startAnimation') and call it after you've created your object.

EDIT:

Try this:

import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.Timer;

    public class Frame implements Runnable, ActionListener
    {
        final JFrame window;
        final Canvas myCanvas;

        public Frame(){
            this.window = new JFrame("Frame");
            this.myCanvas = new Canvas();
            this.window.add(this.myCanvas);
            this.window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            this.window.setBounds(30, 30, 700, 500);
            this.window.setFocusable(true);
            this.window.setFocusTraversalKeysEnabled(false);
            this.window.setVisible(true);
        }

        public void startApp() {
            final Thread t = new Thread(this);
            t.start();
        }

        public void run(){
            final Timer timer = new Timer (1000,this);
            timer.start();
        }

        public void actionPerformed(ActionEvent e){
            myCanvas.updateGame();
            window.repaint();
        }

        public static void main(String[] args) {
            final Frame f = new Frame();
            f.startApp();
        }
    }

    class Canvas extends JPanel {
        int x = 10;
        int y = 10;
        public void updateGame() {
            x++;
        }

        @Override
        protected void paintComponent(Graphics g){
            super.paintComponent(g);
            Graphics2D g2 = (Graphics2D) g;
            g.drawString("hi", this.x, this.y);
            System.out.println("paint");
        }
    }