Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Why does this JLabel have 2 positions?

I’m making this program where a JLabel controlled by the user will move on a 500×500 frame, but for some reason it seems to have two positions and when it moves it just flickers between them. What is causing this?

This is how it currently looks like

Here’s the main window:

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

package guipkg1;

import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;

import javax.swing.*;

import guipkg1.PlayerMove;

public class KeyListenerPage extends JFrame implements KeyListener {
    public static JLabel player = new JLabel();
    public static boolean isGoingLeft = false;
    public static boolean isGoingUp = false;
    public static boolean isGoingRight = false;
    public static boolean isGoingDown = false;
    PlayerMove pmove = new PlayerMove();
    KeyListenerPage(){
        this.setDefaultCloseOperation(HIDE_ON_CLOSE);
        this.setSize(500,500);
        this.setLayout(null);
        this.setVisible(false);
        this.addKeyListener(this);
        
        player.setBounds(0,0,50,50);
        player.setText(":)");
        this.add(player);
        
        
        
        pmove.start();
    } 
        
    @Override
    public void keyTyped(KeyEvent e) {
        // TODO Auto-generated method stub
        
    }
    @Override
    public void keyPressed(KeyEvent e) {
        // TODO Auto-generated method stub
        if(e.getKeyCode()==37 || e.getKeyCode()==65) {
            isGoingLeft = true;
            System.out.println("[KeyListenerPage] going left");
        } else if(e.getKeyCode()==38 || e.getKeyCode()==87) {
            isGoingUp = true;
            System.out.println("[KeyListenerPage] going up");
        } else if(e.getKeyCode()==39 || e.getKeyCode()==68) {
            isGoingRight = true;
            System.out.println("[KeyListenerPage] going right");
        } else if(e.getKeyCode()==40 || e.getKeyCode()==83) {
            isGoingDown = true;
            System.out.println("[KeyListenerPage] going down");
        }
        
    }
    @Override
    public void keyReleased(KeyEvent e) {
        // TODO Auto-generated method stub
        if(e.getKeyCode()==37 || e.getKeyCode()==65) {
            isGoingLeft = false;
            System.out.println("[KeyListenerPage] stopped going left");
        } else if(e.getKeyCode()==38 || e.getKeyCode()==87) {
            isGoingUp = false;
            System.out.println("[KeyListenerPage] stopped going up");
        } else if(e.getKeyCode()==39 || e.getKeyCode()==68) {
            isGoingRight = false;
            System.out.println("[KeyListenerPage] stopped going right");
        } else if(e.getKeyCode()==40 || e.getKeyCode()==83) {
            isGoingDown = false;
            System.out.println("[KeyListenerPage] stopped going down");
        }
    }
}

And the thread moving the player:

package guipkg1;

import javax.swing.JLabel;

public class PlayerMove extends Thread implements Runnable {
    boolean movingLeft = KeyListenerPage.isGoingLeft;
    boolean movingUp = KeyListenerPage.isGoingUp;
    boolean movingRight = KeyListenerPage.isGoingRight;
    boolean movingDown = KeyListenerPage.isGoingDown;
    JLabel player = KeyListenerPage.player;
    boolean canMoveLeft = false;
    boolean canMoveRight = true;
    boolean canMoveUp = false;
    boolean canMoveDown = true;
    public void run() {
        System.out.println("running");
        while(true) {
            try {
                Thread.sleep(20);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            movingLeft = KeyListenerPage.isGoingLeft;
            movingUp = KeyListenerPage.isGoingUp;
            movingRight = KeyListenerPage.isGoingRight;
            movingDown = KeyListenerPage.isGoingDown;
            if(movingLeft && canMoveLeft) {
                player.setBounds(player.getWidth(), player.getHeight(), player.getX()-10, player.getY());
                player.setVisible(true);
                if(player.getX()<=0) {
                    canMoveLeft = false;
                }
                if(player.getX()<490) {
                    canMoveRight = true;
                }
            } 
            if(movingRight && canMoveRight) {
                player.setBounds(player.getWidth(), player.getHeight(), player.getX()+10, player.getY());
                player.setVisible(true);
                if(player.getX()>0) {
                    canMoveLeft = true;
                }
                if(player.getX()>=490) {
                    canMoveRight = false;
                }
            }
            if(movingUp && canMoveUp) {
                player.setBounds(player.getWidth(), player.getHeight(), player.getX(), player.getY()-10);
                player.setVisible(true);
                if(player.getY()<=0) {
                    canMoveUp = false;
                }
                if(player.getY()<490) {
                    canMoveDown = true;
                }
            } 
            if(movingDown && canMoveDown) {
                player.setBounds(player.getWidth(), player.getHeight(), player.getX(), player.getY()+10);
                player.setVisible(true);
                if(player.getY()>0) {
                    canMoveUp = true;
                }
                if(player.getY()>=490) {
                    canMoveDown = false;
                }
            } 
            
        }
    }
}

>Solution :

Why does it flicker?

Because your arguments to player.setBounds() are in the wrong order.

According to the JLabel#setBounds() JavaDoc the arguments are in the order x, y, width, height.

But your code calls the method with the arguments

player.setBounds(player.getWidth(), player.getHeight(), player.getX(), player.getY()+10);

where it should be

player.setBounds(player.getX(), player.getY()+10, player.getWidth(), player.getHeight());

Also note that Swing is not thread-safe. If you want to change anything on a displayed Swing component you must do it on the Swing EDT, for example by rewriting PlayerMove.run() as

public void run() {
    System.out.println("running");
    while(true) {
        try {
            Thread.sleep(20);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        SwingUtilities.invokeLater(this::move);
    }
}

And moving the remaining code from PlayerMove.run() into a new move() method:

private void move() {
    movingLeft = KeyListenerPage.isGoingLeft;
    movingUp = KeyListenerPage.isGoingUp;
    movingRight = KeyListenerPage.isGoingRight;
    movingDown = KeyListenerPage.isGoingDown;
    if(movingLeft && canMoveLeft) {
        player.setBounds(player.getX()-10, player.getY(), player.getWidth(), player.getHeight());
        player.setVisible(true);
        if(player.getX()<=0) {
            canMoveLeft = false;
        }
        if(player.getX()<490) {
            canMoveRight = true;
        }
    }
    if(movingRight && canMoveRight) {
        player.setBounds(player.getX()+10, player.getY(), player.getWidth(), player.getHeight());
        player.setVisible(true);
        if(player.getX()>0) {
            canMoveLeft = true;
        }
        if(player.getX()>=490) {
            canMoveRight = false;
        }
    }
    if(movingUp && canMoveUp) {
        player.setBounds(player.getX(), player.getY()-10, player.getWidth(), player.getHeight());
        player.setVisible(true);
        if(player.getY()<=0) {
            canMoveUp = false;
        }
        if(player.getY()<490) {
            canMoveDown = true;
        }
    }
    if(movingDown && canMoveDown) {
        player.setBounds(player.getX(), player.getY()+10, player.getWidth(), player.getHeight());
        player.setVisible(true);
        if(player.getY()>0) {
            canMoveUp = true;
        }
        if(player.getY()>=490) {
            canMoveDown = false;
        }
    }
}

As MadProgrammer has already commented the better way would be to use a Swing Timer

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading