Search code examples
javaswingjbuttonimageicon

why won't my jbutton with image show up with graphics java


I'm having trouble with my jbutton not displaying. If i do not use paintComponent, then my JButtons with images show up no problem. However now, the image does not show up. If i hover over where it should be, the image shows up for one second. So it's like the button is still there, just maybe below the background?

public class Game extends JPanel implements KeyListener, ActionListener {

    //layout variables
    private ImageIcon right,left,up,down;
    private JButton rightButton,leftButton,upButton,downButton;

    //play variables
    private boolean play=false;
    private int score=0;

    private int paddleX= 200; //paddle X position
    private int paddleY= 300; //paddle Y pos
    private int ballX= 210; //ball x position
    private int ballY= 260; //ball y position
    private int ballXdir=-1; //x direction
    private int ballYdir=-2; //y direction

    private Timer time; //my timer

    public Game() {
        Display(); //display the layout
        addKeyListener(this);
        setFocusable(true);
        setFocusTraversalKeysEnabled(false);
        time= new Timer(8,this);
        time.start();
    }

    public void Display(){

        //setLayout
        this.setLayout(null);

        //Setting the Images
        //right = new ImageIcon(getClass().getResource("images\\rightIcon.png"));
        left = new ImageIcon(getClass().getResource("images\\leftIcon.png"));
        up = new ImageIcon(getClass().getResource("images\\upIcon.png"));
        down = new ImageIcon(getClass().getResource("images\\downIcon.png"));

        //Setting the JButtons for the arrow images
        rightButton= new JButton("right");
        rightButton.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                if(paddleX>=400){
                    paddleX=400;
                }
                else{
                    moveRight();
                }
                repaint();
            }
        });
        //rightButton.setOpaque(false);
        //rightButton.setContentAreaFilled(false);
        //rightButton.setBorderPainted(false);

        leftButton= new JButton(left);
        leftButton.setOpaque(false);
        leftButton.setContentAreaFilled(false);
        leftButton.setBorderPainted(false);

        upButton= new JButton(up);
        upButton.setOpaque(false);
        upButton.setContentAreaFilled(false);
        upButton.setBorderPainted(false);

        downButton= new JButton(down);
        downButton.setOpaque(false);
        downButton.setContentAreaFilled(false);
        downButton.setBorderPainted(false);

        //setting image bounds and adding it to screen
        rightButton.setBounds(135,450,50,50);
        leftButton.setBounds(45,450,50,50);
        upButton.setBounds(90,400,50,50);
        downButton.setBounds(90,500,50,50);

        //rightButton.addActionListener(this);
        leftButton.addActionListener(this);

        add(upButton);
        add(downButton);
        add(leftButton);
        add(rightButton);



    }

    //painting the screen with graphics
    public void paintComponent(Graphics g) {
        super.paintComponent(g);
        g.setColor(Color.BLACK);
        g.fillRect(25,25,425,300); //game area

        //drawing the paddle
        g.setColor(Color.YELLOW);
        g.fillRect(paddleX,paddleY,50,8);

        //drawing the ball
        g.setColor(Color.PINK);
        g.fillOval(ballX,ballY,20,20);

        g.dispose();
    }

    @Override
    public void actionPerformed(ActionEvent e) {
        time.start();

        if(e.getSource()==right) {
            if(paddleX>=400){
                paddleX=400;
            }
            else{
                moveRight();
            }           
        }

        if(e.getSource()==left) {
            if(paddleX<35){
                paddleX=35;
            }
            else{
                moveLeft();
            }
        }

        repaint();

    }
    @Override
    public void keyPressed(KeyEvent e) {
        if(e.getKeyCode()==KeyEvent.VK_RIGHT){
            if(paddleX>=400){
                paddleX=400;
            }
            else{
                moveRight();
            }

        }
        if(e.getKeyCode()==KeyEvent.VK_LEFT){
            if(paddleX<35){
                paddleX=35;
            }
            else{
                moveLeft();
            }
        }

    }
    @Override
    public void keyReleased(KeyEvent arg0) {

    }

    @Override
    public void keyTyped(KeyEvent arg0) {

    }

    public void moveRight(){
        play=true;
        paddleX+=10;
    }

    public void moveLeft(){
        play=true;
        paddleX-=10;
    }


}

Solution

  • I highly recommend having a look at Performing Custom Painting and Painting in AWT and Swing as it will explain how the painting system works.

    Basically, you are passed a reference to the Graphics context which is currently been used to perform the current paint pass, via the paintComponent method. This is a shared resource. All components involved in the paint pass are passed the same Graphics context.

    By calling dispose, you are releasing all the underlying resources for the context, which can, on some systems, prevent other components from been painted.

    But they paint when I move my mouse over them

    Because components can be painted independently of their parent, but you also call repaint on the parent component, which will, you guessed it, paint it's children.

    Recommendations

    • Create a custom component dedicated solely to performing the custom painting operations (and possible some of the other basic game functions)
    • Create another component to hold the buttons (and make use of appropriate layouts)
    • Use a some kind of data model which is shared between them. This model will hold the state of the "actions" (ie up/down/left/right) and the "engine" will use this information to update the state of the game.
    • Make use of the Key bindings API which will solve the unreliability issues associated with KeyListener