Java repaint() not calling paintComponent

422 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 newFrame 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);
    Thread t = new Thread(this);
    t.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("Output1");
}

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

Output1 is printed multiple times but Output2 is never printed. Why isn't the paintComponent method being called by repaint?

2

There are 2 answers

1
River On

You only have "Ouput1" printed ever. There is no "Output2" printed anywhere.

0
MadProgrammer On

The core problem is within your ActionListener...

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

When you call window.add, the JFrame has to first remove myCanvas and then re-add it, revalidate the layout and schedule a repaint, all of this is taking time, in the mean time, you've jumped in repeated the process, setting a situation in which the framework simply can't keep up with you.

Instead, add window.add(myCanvas); to the constructor

public void createFrame() {
    window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    window.setBounds(30, 30, 700, 500);
    window.setFocusable(true);
    window.setFocusTraversalKeysEnabled(false);
    window.setVisible(true);
    window.add(myCanvas);
    Timer timer = new Timer(17, this);
    timer.start();
}

Also, there is simply no need to use a Thread to start a Timer, it's just confusing the issue.

Beware that Java already has classes called Frame and Canvas, which could add additional confusion to some developers (especially those who don't have access to the source)