1

I am learning Java and I've tried to build an app that drops a ball when I click on the panel. The problem is that when the oval is painted its moving so fast that even setting Thread.sleep to max value just makes it barely noticable. How can I slow it down?

public void paintComponent(Graphics g) {
        super.paintComponent(g);
        Graphics2D g2 = (Graphics2D) g;
        g2.setPaint(Color.red);
        g2.drawOval(x,y,20,20);

        Thread thread = new Thread() {
            public void run() {
              while (true) {
                y = y + 1;
                repaint();
                try {
                  Thread.sleep(2147483647);
                } 
                catch (InterruptedException ex) {
                }
              }
            }
          };
          thread.start();
    }
ton
  • 21
  • 2
  • 2
    1) Don't use `while(true)` in a Swing application, even less inside the `paintComponent(...)` method as it gets called several times and you have no control over when it gets called. 2) Don't use `Thread.sleep(...)` either as it blocks the EDT. See [this example](https://stackoverflow.com/questions/46778963/drawingpanel-color-change-with-displacement/46792479#46792479) or [this one](https://stackoverflow.com/questions/42404270/jcomponent-stops-getting-rendered-once-it-goes-off-the-screen/42404808#42404808) – Frakcool Jun 04 '19 at 20:17
  • 2
    @Frakcool even inside a new Thread??? I would either say do not create a new Thread inside `paintX` methods (which can and will be called a LOT of time) – user85421 Jun 04 '19 at 20:18
  • 1
    @ton as I see it, you are creating and starting a new Thread inside `paintComponent` that increases y and calls `repaint` which in turn will cause `paintComponent` to be called again and creating a new Thread that will also increment `y` and call `repaint` another time starting all again.... I wonder there was no OOM exception, probably because `paintComponent` is called on EDT -- just move the Thread creation/start out of that method – user85421 Jun 04 '19 at 20:26
  • 1
    It won't block the EDT if you execute it on another Thread, however remove it from the painting methods for the reasons mentioned before – Frakcool Jun 04 '19 at 20:51

2 Answers2

1

I have not tried your program in my own environment, but from what I know, it seems like what is moving your ball is the:

y = y + 1; 

line, therefore you could probably consider changing that to a smaller number, most likely a double. Also, as was already mentioned, maybe you can try not using the:

while (true)

statement, as that will just always and forever evaluate to true and it's not the biggest issue, but maybe you can think of using something else like using something that has to do with the y variable like: while (y < 768 ) or even something like a for loop depending on what it is you're doing.

Hopefully this helps, and I would also advise you take a look at this answer here: Java Graphics Updating Too Fast

Wishing you the best!

TechWiz77
  • 69
  • 1
  • 1
  • 8
  • 1
    Thanks, but I can't change y to double because it's used in g2.drawOval(x,y,20,20); and drawOval only accepts int. – ton Jun 04 '19 at 20:37
  • 1
    the `y = y + 1` is not the problem, `Thread.sleep(2147483647)` is a very long time, a bit more than 24 days, the loop is effectively not being repeated (I doubt anyone is waiting so long, nor that the program is running that long) – user85421 Jun 04 '19 at 20:50
0
  • Get rid of creating the thread in the paintComponent method.

  • You need to use the java Swing Timer with an actonListener to
    increment the x and y coordinates and then call repaint(). Check the Java API for details.

  • When you start the program, use SwingUtilities.invokeLater(()->new className()) to invoke the class. This schedules the app in queue for processing in the Event Dispatch Thread (EDT). All events and repainting need to be handled in the EDT.

  • In your paintComponent method, set anti-aliasing using Graphics2D via setRenderingHints. It is also explained in the Java API. It will make your graphics appear smoother by averaging the edges.

WJS
  • 36,363
  • 4
  • 24
  • 39