Search code examples
javaswingjlabel

JLabel run function form runnable interface is not being called


So I read that run function from Runnable interface is automatically called but it is not working for me (run is not being called). This is my first time doing anything in java so I might have done something stupid. The following code is supposed to move a rectangle across the screen. The rectangle is drawn but it is not moving.

Main:

    public class Label extends JLabel{

    Game game;

    public Label(Game game){
       this.game = game;
    }

    public void paint(Graphics gfx){
        game.render(gfx);
    }
}

Frmae:

import javax.swing.*;
import java.awt.*;

public class Frame extends JFrame implements Runnable{

    Game game;

    public Frame(Label label, Game game) {
        this.setSize(600, 600);
        this.setTitle("idk");
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        this.setVisible(true);
        this.setEnabled(true);
        this.game = game;
        this.setContentPane(label);
    }

    public void run(){
        game.update();
        try {
            Thread.sleep(20);
        }
        catch(InterruptedException ex){}
    }
}

Label:

import javax.swing.*;
import java.awt.*;

public class Label extends JLabel{

    Game game;

    public Label(Game game){
       this.game = game;
    }

    public void paint(Graphics gfx){
        game.render(gfx);
    }
}

Game:

import java.awt.*;

public class Game {

    float x = 0;
    float y = 0;
    float w = 20;
    float h = 20;

    void render(Graphics gfx){
        gfx.fillRect((int)x, (int)y, (int)w, (int)h);
    }

    void update(){
        x += 0.1f;
        System.out.println(x);
    }
}

Solution

  • You need to create a main method where you create a new Thread object, passing the Runnable class (i.e., Frame in your case) in that Thread instance, and subsequently start the Thread. See below:

    public class Main
    {     
        public static void main(String args[])  
        {    
            Game g = new Game();
            Label l = new Label(g);
            Frame f = new Frame(l, g);    
            Thread t1 =new Thread(f);   
            // this will call run() method in Frame class 
            t1.start();    
        }    
    } 
    

    EDIT: Also, your Frame class should look like the one below. A Thread executes its run method once, and then it is considered completed. If you want to loop, you have to do it yourself (below a while(true) is used, which can be changed to some variable that you can turn to false when you want the program to exit). Finally, make sure to call repaint() after game.update() for the drawing to take effect.

    import javax.swing.*;
    import java.awt.*;
    
    public class Frame extends JFrame implements Runnable{
    
        Game game;
        Label label;
        public Frame(Label label, Game game) {
            this.label = label;
            this.setSize(600, 600);
            this.setTitle("idk");
            this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            this.setVisible(true);
            this.setEnabled(true);
            this.game = game;
            this.setContentPane(label);
        }
    
        @Override
        public void run(){
            while(true) {
                game.update();
                label.repaint();
                try {
                    Thread.sleep(5);
                }
                catch(InterruptedException ex){}
            }
        }
    }