Results 1 to 6 of 6
- 09-04-2012, 07:54 PM #1
Senior Member
- Join Date
- Oct 2011
- Location
- Sweden
- Posts
- 123
- Rep Power
- 0
Animating a moving ball - repainting one component
Hello!
Time for me to start a thread about a problem that I've run into. The course I'm taking is at the moment focusing on graphics and drawing components with Java. Personally, I couldn't find this less interesting, but nonetheless I'll just have to deal with it and do it.
I'm trying to create a program in which a ball bounces around inside a JPanel. My layout is a GridBagLayout where I've placed two buttons and a JPanel inside a first JPanel. The buttons are to alter the speed of the ball movement.
When running the code, it appears as if the "repaint()" method repaints the whole JPanel in which the ball is moving. This is, when I'm thinking of it, quite logic, but not what I want it to do. Of course, I only want to repaint the ball inside the panel, not repaint the panel inside the panel itself.
This is what it looks like when I'm commenting out the repaint()-method.

When the repaint()-method is called:

The code that I'm using:
BallDemo.java
Nothing is wrong here, though to compile this is needed. This creates a new object of the BallPanel class.
BallPanel.javaJava Code:import java.awt.Color; import java.awt.EventQueue; import javax.swing.JFrame; import javax.swing.JPanel; import javax.swing.UIManager; import javax.swing.UIManager.LookAndFeelInfo; import javax.swing.border.EmptyBorder; import java.awt.GridBagLayout; import java.awt.GridBagConstraints; import javax.swing.JButton; import java.awt.Insets; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; public class BallDemo extends JFrame { private static final long serialVersionUID = 1L; private JPanel contentPane; /** * Launch the application. */ public static void main(String[] args) { EventQueue.invokeLater(new Runnable() { public void run() { try { for (LookAndFeelInfo info : UIManager.getInstalledLookAndFeels()) { if ("Nimbus".equals(info.getName())) { UIManager.setLookAndFeel(info.getClassName()); break; } } } catch (Exception e) { e.printStackTrace(); } try { BallDemo frame = new BallDemo(); frame.setTitle("BallDemo!"); frame.setVisible(true); } catch (Exception e) { e.printStackTrace(); } } }); } /** * Create the frame. */ public BallDemo() { setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); setBounds(100, 100, 800, 600); contentPane = new JPanel(); contentPane.setBorder(new EmptyBorder(5, 5, 5, 5)); setContentPane(contentPane); GridBagLayout gbl_contentPane = new GridBagLayout(); gbl_contentPane.columnWidths = new int[]{0, 0}; gbl_contentPane.rowHeights = new int[]{0, 0, 0, 0, 0}; gbl_contentPane.columnWeights = new double[]{1.0, Double.MIN_VALUE}; gbl_contentPane.rowWeights = new double[]{1.0, 0.0, 0.0, 0.0, Double.MIN_VALUE}; contentPane.setLayout(gbl_contentPane); //Create the panel on which to draw BallPanel panelCanvas = new BallPanel(); GridBagConstraints gbc = new GridBagConstraints(); gbc.gridheight = 2; gbc.gridwidth = 2; gbc.insets = new Insets(0, 0, 5, 0); gbc.fill = GridBagConstraints.BOTH; gbc.gridx = 0; gbc.gridy = 0; contentPane.add(panelCanvas, gbc); panelCanvas.setBackground(Color.GRAY); //Controller button for speed change (decrease) JButton decrButton = new JButton("Decrease speed"); gbc.gridx = 0; gbc.gridy = 3; gbc.weightx = 0.5; gbc.gridwidth = 2; contentPane.add(decrButton, gbc); decrButton.addActionListener(new ActionListener(){ public void actionPerformed(ActionEvent e) { // TODO add code here for decreasing speed } }); //Controller button for speed change (increase) JButton incrButton = new JButton("Increase speed"); gbc.gridx = 0; gbc.gridy = 1; gbc.weightx = 0.5; contentPane.add(incrButton, gbc); incrButton.addActionListener(new ActionListener(){ public void actionPerformed(ActionEvent e) { // TODO add code here for increasings speed } }); } }
This is where repaint()-method is called within the ActionListener to the timer that sets the update interval for the animation.
Ball.javaJava Code:import java.awt.Color; import java.awt.Graphics; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import javax.swing.BorderFactory; import javax.swing.JPanel; import javax.swing.Timer; public class BallPanel extends JPanel{ private Ball ball = new Ball(1, 1); private int animationUpdater = 40; private Timer timer; /** * Constructor for BallPanel that is the canvas where the ball is moving. */ public BallPanel(){ setBorder(BorderFactory.createLineBorder(Color.BLACK)); timer = new Timer(animationUpdater, performer); timer.start(); } public void paintComponent(Graphics g){ g.setColor(Color.GREEN); ball.draw(g); } /** * ActionListener that runs accordingly to timer. */ private ActionListener performer = new ActionListener(){ public void actionPerformed(ActionEvent arg0) { ball.setBounds(getWidth(), getHeight()); ball.animate(); repaint(); } }; }
This is the code for the ball itself.
So, what could be my problem?Java Code:import java.awt.Graphics; /** * Class for a Ball object that is moved inside a JPanel. * When constructor called, creates a Ball with random diameter somewhere between 15 and 45 pixels. * */ public class Ball { int d = 25; int rightBorder; int topBorder; private int x; private int y; private int speedX = 3; private int speedY = 3; /** * Constructor for Ball object. * @param x * @param y */ public Ball(int x, int y){ this.x = x; this.y = y; } /** * Draw method for Ball object. * @param g */ public void draw(Graphics g){ System.out.println(x); g.fillOval(x, y, d, d); } /** * Define the boundaries of the area that the ball is moving within. * @param width Width of ball * @param height */ public void setBounds(int width, int height){ rightBorder = width - d; topBorder = height - d; } /** * Method for animating the movement of the ball. */ public void animate(){ //Set the new location of the coordinates. x += speedX; y += speedY; //Check if the X-coordinate is at the left side of the panel, set to zero and then reverse direction. if (x < 0){ x = 0; x = -speedX; //Check if X-coordinate is at the right side of panel, reverse direction. }else if(x > rightBorder){ x = rightBorder; x = -speedX; } //Check the same for the Y-coordinates. if (y < 0){ y = 0; y = -speedY; }else if(y > topBorder){ y = topBorder; y = -speedY; } } // public int getX() { // return x; // } // // // public void setX(int x) { // this.x = x; // } }
When looking at program while running, or just the second picture above, one sees that there are many several balls that together form a line. Why isn't the ball repainted? It appears as if it's being drawn all over again and leaving previous ball(s) in place.
Also, you can see that the borderline of the panel BallPanel is duplicated to the left in the second pic. This suggest to me that the whole panel is being redrawn, though perhaps only one time? (Otherwise more borderlines would appear?)
And finally, one of the buttons appear in the top when the repaint()-method is called. It is not click-able, though it's highlighted when the bottom button is highlighted, and it also changes to the other button when you hover the mouse over the other bottom button.
I'm grateful for any thoughts and tips!
On a more off topic question, what is the general view of importance of graphics in Java? I have no plans on becoming a game developer or anything close to graphics designer, so why would I (sorry for the harsh words) waste my time learning to do this? Of course I am interested in coding GUI's, but I don't see this as very close to that.
Thank you,
Z!
EDIT:
I changed the code of the Ball class so it looks like this:
This show that I was correct about the idea that repaint()-method draws a new ball and leaves the old one. I get several balls instead of one long green line.Java Code:private int speedX = 26; private int speedY = 26;
Last edited by Zyril; 09-04-2012 at 08:03 PM.
- 09-04-2012, 09:13 PM #2
Re: Animating a moving ball - repainting one component
The streaked green strip looks like a history of where the ball has been. If you clear the screen by calling the super.paintComponent() method, the history will be erased before the new ball is drawn.
If you don't understand my response, don't ignore it, ask a question.
- 09-04-2012, 09:29 PM #3
Senior Member
- Join Date
- Oct 2011
- Location
- Sweden
- Posts
- 123
- Rep Power
- 0
Re: Animating a moving ball - repainting one component
That did the trick, thank you Norm!
So, let me see if I understand this correctly.
I'm overriding the JComponents paintmethod with my own paintComponent(), and if I then want to clear the background area where I'm painting, I have to call the parentclass paintComponent()..?
Following, should super.paintComponent() always be called, or are there are scenarios when you can omit this?
The visual artifacts I had when I didn't call super.paintComponent(), were they there because I didn't draw the entire background?
- 09-04-2012, 10:29 PM #4
Re: Animating a moving ball - repainting one component
Most of the time you should call the super method. I don't know when not to.
If you don't understand my response, don't ignore it, ask a question.
- 09-05-2012, 12:05 AM #5
Re: Animating a moving ball - repainting one component
If your custom painting code addresses every pixel of the component's client area, you can safely omit the call to the super implementation. An example could be
Another example could be when you paint a gradient or tiled background scaled to the size of the component.Java Code:g.drawImage(0, 0, getWidth(), getHeight(), this);
But. Whenever I write such code, I leave a commented-out call to the super implementation to remind me or anyone else who reads the code that the omission was intentional. I find that more effective than a comment to the same effect.dbJava Code:@Override protected void paintComponent(Graphics g) { // super.paintComponent(g); ... other painting code .. }Why do they call it rush hour when nothing moves? - Robin Williams
- 09-05-2012, 06:13 AM #6
Senior Member
- Join Date
- Oct 2011
- Location
- Sweden
- Posts
- 123
- Rep Power
- 0
Similar Threads
-
Ball moving across the screen?
By Slicknife in forum New To JavaReplies: 1Last Post: 05-29-2012, 11:53 PM -
Moving a ball
By jsmasand in forum Java 2DReplies: 5Last Post: 04-27-2012, 03:34 AM -
Ball Move to mouse not animating.
By Jossos in forum New To JavaReplies: 6Last Post: 01-05-2012, 01:42 PM -
Ball not moving
By Eleeist in forum New To JavaReplies: 7Last Post: 01-04-2012, 11:27 PM -
Moving a ball with Arrow Keys
By kekcklemen in forum Java AppletsReplies: 5Last Post: 02-25-2011, 10:15 PM


1Likes
LinkBack URL
About LinkBacks
Reply With Quote

Bookmarks