0

I'm trying to make a code that will move a red ball with JButtons (and later add keybinders). There are no problems when I compile and when I run I see the ball but the JButtons won't affect him. I think the problem might be that the ball is drawed only once and then is called again and again without being drawed in the new position but I don't know how to fix that. 1) does anybody know how I can fix that? 2) is there a way to change the shape of a JPanel to a ball? (that would probably be a simpler way to move him)

package il.co.atlantis;

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

import javax.swing.*;


import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;

public class KeyBinders implements ActionListener {

boolean right=true, left=false, up=false, down=false, inGame=true;
JPanel backgroundPanel, bannerPanel, scorePanel, applePanel;
JLabel currentScoreLabel, highestScoreLabel;
JButton upButton, downButton, rightButton, leftButton;
long millis =System.currentTimeMillis(), millisn =System.currentTimeMillis();
public static final int WID = 10, HEI = 10;
public static int x1 = 100, y1 = 100;
public class MyGraphics extends JComponent {

    private static final long serialVersionUID = 1L;

    MyGraphics() {
        setPreferredSize(new Dimension(700, 500));
    }

    public void moveRight(){
    ++x1;
    }

    public void moveLeft(){
    --x1;
    }

    public void moveUp(){
    --y1;
    }

    public void moveDown(){
    ++y1;
    }

    public void paintComponent(Graphics g){
        super.paintComponents(g);
        g.setColor(Color.red);
        g.fillOval(x1, y1, WID, HEI);
    }

}


public JPanel CreateContentPane (){
    JPanel totalGUI = new JPanel();
    totalGUI.setLayout(null);

    backgroundPanel = new JPanel();
    backgroundPanel.setBackground(Color.black);
    backgroundPanel.setLocation(100, 10);
    backgroundPanel.setSize(700, 500);
    totalGUI.add(backgroundPanel);

    upButton = new JButton("up");
    upButton.setLocation(0,0);
    upButton.setSize(50,50);
    totalGUI.add(upButton);

    downButton = new JButton ("down");
    downButton.setLocation(0,50);
    downButton.setSize(50,50);
    totalGUI.add(downButton);

    rightButton = new JButton("right");
    rightButton.setLocation(0,100);
    rightButton.setSize(50,50);
    totalGUI.add(rightButton);

    leftButton = new JButton("left");
    leftButton.setLocation(0,150);
    leftButton.setSize(50,50);
    totalGUI.add(leftButton);


    MyGraphics tr = new MyGraphics();
    tr.setLocation(100, 100);
    backgroundPanel.add(tr);


    return totalGUI;
}

public void ActionPerformed(ActionEvent h){
    if(h.getSource() == upButton) {
        --y1;
    }
    else if(h.getSource() == downButton){
        ++y1;
    }
    else if(h.getSource() == leftButton){
        --x1;
    }
    else if(h.getSource() == rightButton){
        ++x1;
    }
}

private static void createAndShowGUI() {

    JFrame.setDefaultLookAndFeelDecorated(true);
    JFrame frame = new JFrame("[=] JButton Scores! [=]");

    //Create and set up the content pane.
    KeyBinders demo = new KeyBinders();
    frame.setContentPane(demo.CreateContentPane());

    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.setSize(280, 190);
    frame.setVisible(true);
}

public static void main(String[] args) {
    //Schedule a job for the event-dispatching thread:
    //creating and showing this application's GUI.
    SwingUtilities.invokeLater(new Runnable() {

        public void run() {
            createAndShowGUI();

        }
    });
}

public KeyBinders() {
    // TODO Auto-generated constructor stub
}

@Override
public void actionPerformed(ActionEvent arg0) {
    // TODO Auto-generated method stub

}


}
Atlantis
  • 592
  • 5
  • 23

2 Answers2

2

When you invoke action event, actionPerformed() function gets called, as you did. You have change the drawing position too. you need to call Component.repaint() which tells Swing t hat the entire component, whichever one you specified to be repainted , must be updated . So add this function calling in your code. For example:

public void ActionPerformed(ActionEvent h){
    if(h.getSource() == upButton) {
        --y1;
    }
    else if(h.getSource() == downButton){
        ++y1;
    }
    else if(h.getSource() == leftButton){
        --x1;
    }
    else if(h.getSource() == rightButton){
        ++x1;
    }
   repaint();
}

Check the tutorial: Performing Custom Painting.

Sage
  • 15,290
  • 3
  • 33
  • 38
  • I tried to add frame.repaint(); and MyGraphics tr = new MyGraphics(); tr.validate(); tr.repaint(); – Atlantis Oct 24 '13 at 18:09
  • MyGraphics tr = new MyGraphics(); tr.validate(); tr.repaint(); – Atlantis Oct 24 '13 at 18:12
  • `graphics.repaint()` ? I wrote: `component.repaint()`; – Sage Oct 24 '13 at 19:03
  • @עמוסרום , No please pay attention. I used to component to represent any JComponent, nothing specific. you need to call repaint() on the component you are drawing and want to update the component with your drawing. If it is `MyGraphics extends JComponent`, then you need to call `repaint()` on the instance of `MyGraphics` on each action event. – Sage Oct 24 '13 at 19:33
1

There's a method called repaint() you should familiarize yourself with.

When called on a component (such as a JFrame) it'll repaint all the components within. Naturally you need to call it if you want your changes to become visible on the screen.

As for custom painting, you shouldn't use a Component at all, rather use the Graphics.fillRect/fillOval etc. methods to just draw what you want.

See here for the custom painting tutorial.

Kayaman
  • 72,141
  • 5
  • 83
  • 121