2

I'm in front of a big issue and I find any explanation.

I'm currently playing a little with Java and it seems that my programs are very slow (like 5-10 FPS even if I specify my thread to run at 60 FPS), unless I move my mouse over the window, even if my window doesn't have the focus. I had the same issue with several examples and I give to you a very short one within my issue occurs.

package com.coukaratcha;

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;

import javax.swing.JFrame;
import javax.swing.JPanel;

public class BouncingBall  extends JFrame {

    private int x;
    private int y;
    private int vx;
    private int vy;

    public BouncingBall(){
        super("Bouncing Ball");

        this.x = 300;
        this.y = 200;

        this.vx = 5;
        this.vy = -2;

        this.setDefaultCloseOperation(EXIT_ON_CLOSE);

        this.setResizable(false);

        final JPanel content = new JPanel(){
            protected void paintComponent(Graphics g){
                super.paintComponent(g);

                g.setColor(Color.WHITE);

                g.fillOval(x-10, y-10, 10, 10);
            }
        };

        content.setPreferredSize(new Dimension(600, 400));

        content.setBackground(Color.BLACK);

        this.setContentPane(content);

        Thread thread = new Thread(new Runnable(){
            public void run(){
                while(true){

                    updatePhysics();

                    content.repaint();

                    try{
                        Thread.sleep(1000/60);
                    }
                    catch (InterruptedException e){
                        ;
                    }
                }
            }
        });

        this.pack();
        this.setLocationRelativeTo(null);
        this.setVisible(true);

        thread.start();
    }

    public void updatePhysics(){
        if (x > 595 || x < 10){
            vx*= -1;
        }

        if (y > 395 || y < 10){
            vy*= -1;
        }

        x+=vx;
        y+=vy;
    }

    public static void main(String[] args) {
        BouncingBall ball = new BouncingBall();
    }
}

I tried this code on some Windows and it works perfectly, but on my Fedora 20/21 or the Ubuntu of a friend, the slowing strikes again. It's compiled with Java 1.8.

Thank you in advance for your help.

[EDIT] After @jtahlborn invite me to use the so called EDT, without clearly explaining how to do that by the way, I've made some modifications in my code and here is the last version where exactly the same issue occurs. I must do something bad, in this case : someone would be nice enough to explain me how to properly do ? Otherwise, I don't have any idea how to avoid this problem. For new arrivals, I've changed the Thread part (compare the two codes), in the constructor.

My new code :

package com.coukaratcha;

import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;

import javax.swing.JFrame;
import javax.swing.JPanel;

public class BouncingBall  extends JFrame {

    private int x;
    private int y;
    private int vx;
    private int vy;

    public BouncingBall(){
        super("Bouncing Ball");

        this.x = 300;
        this.y = 200;

        this.vx = 5;
        this.vy = -2;

        this.setDefaultCloseOperation(EXIT_ON_CLOSE);

        this.setResizable(false);

        final JPanel content = new JPanel(){
            protected void paintComponent(Graphics g){
                super.paintComponent(g);

                g.setColor(Color.WHITE);

                g.fillOval(x-10, y-10, 10, 10);
            }
        };

        content.setPreferredSize(new Dimension(600, 400));

        content.setBackground(Color.BLACK);

        this.setContentPane(content);

        Thread thread = new Thread(new Runnable(){
            public void run(){
                while(true){                    
                    updatePhysics();

                    EventQueue.invokeLater(new Runnable(){
                        public void run(){
                            content.repaint();
                        }
                    });

                    try{
                        Thread.sleep(1000/60);
                    }
                    catch (InterruptedException e){
                        ;
                    }
                }
            }
        });

        this.pack();
        this.setLocationRelativeTo(null);
        this.setVisible(true);

        thread.start();
    }

    public void updatePhysics(){
        if (x > 595 || x < 10){
            vx*= -1;
        }

        if (y > 395 || y < 10){
            vy*= -1;
        }

        x+=vx;
        y+=vy;
    }

    public static void main(String[] args) {
        BouncingBall ball = new BouncingBall();
    }

}
lbalazscs
  • 17,474
  • 7
  • 42
  • 50
Coukaratcha
  • 133
  • 2
  • 11
  • Do you use the same JRE ? – merours Dec 15 '14 at 17:12
  • 4
    Your code is broken. you cannot manipulate awt/swing components from a thread other than the EDT. – jtahlborn Dec 15 '14 at 17:14
  • Seems to be linked to the OS/kernel used. It may be due to the scheduling... I am digging on this track but actually didn't find an satisfying answer. Did the app going slower again when the mouse exits the app window ? – Jean-Baptiste Yunès Dec 15 '14 at 17:51
  • @fxm Yes, I use the same version for the JDK and the JRE (i.e. 1.8). – Coukaratcha Dec 15 '14 at 18:09
  • @Jean-BaptisteYunès Yeah, it goes normally unless you move your mouse over the panel. If you leave the panel, it will go back slower, and if you go back to the panel and moving your cursor again, it will go normally again. – Coukaratcha Dec 15 '14 at 18:11
  • Either the Linux scheduler (but it seems strange) or a graphic management system second effect. Remind that every repaint may not lead to a call to paint! A sequence of repaint may lead to only one paint. Is the FPS slower but the graphics coherent to the physics or everything is slower ? – Jean-Baptiste Yunès Dec 15 '14 at 18:19
  • @Jean-BaptisteYunès The physics seem to work well, in other words the ball goes from one side to another in the same amount of time, weither the graphics lag or not. So, I don't think it's linked to my bad using of Thread or whatever. It goes with the same issue without JPanel or repaint, when I've tried with a blinking label text, so I assume it isn't neither linked to the repaint() properties. – Coukaratcha Dec 15 '14 at 18:37
  • So it is a problem of the graphic system... Did you tested with another java version ? 1.7 if you have ? 1.6 ? It may be a bad interaction in between the graphic system and the JVM or it is purely a graphic system problem... – Jean-Baptiste Yunès Dec 15 '14 at 19:27
  • @jtahlborn you are wrong, his code is safe! Calling repaint() outside the EDT is safe because it is intented exactly for that: enqueue from the "outside" a paint request in the EDT. – Jean-Baptiste Yunès Dec 15 '14 at 19:30
  • 1
    @Jean-BaptisteYunès - where do you get this info? i don't see that in the javadoc. – jtahlborn Dec 15 '14 at 20:24
  • possible duplicate of [Why is java application running smoother when moving mouse over it? Video included](http://stackoverflow.com/questions/18684220/why-is-java-application-running-smoother-when-moving-mouse-over-it-video-includ) – Gus Dec 15 '14 at 22:23
  • In *Operating System Concepts*, it is written that most operating systems allocate resources to applications based on the Window manager: if the Window is on top or actively used, it gets more CPU. This is a psychological measure. The total performance of the applications remains the same, but users think that the system is faster, since they *see* more movement. – Willem Van Onsem Dec 15 '14 at 22:26
  • @Gus None of the proposed solutions work. Even the `Timer` solution didn't work, actually i've tried to implement [this solution](http://docs.oracle.com/javase/7/docs/api/javax/swing/Timer.html), but Eclipse disagreed. The `Timer` class doesn't contains any `start()` method. – Coukaratcha Dec 16 '14 at 08:01
  • @CommuSoft It seems that you have the most believable answer of my query. It would explain this strange behavior, but have you an idea on how to solve this problem ? – Coukaratcha Dec 16 '14 at 08:41
  • your current version has threading issues, because you modify `x` and `y` in one thread, then use them to paint the display in a separate thread with no synch between the two. – jtahlborn Dec 16 '14 at 13:51
  • @jtahlborn That's not the point, I don't really care here if there is no sync between physics and graphics. Actually, there's not any desync by the way. My main issue, and the reason I posted here is the awful lag of my application (around 5 FPS). By the way, if I update physics adn graphics in the same thread, basically it guarantees the sync between two of them, and so one doesn't go further thant the other one. Doesnt't it ? – Coukaratcha Dec 16 '14 at 14:34
  • you don't update the graphics in the same thread. you update the graphics in the EDT (using the `invokeLater`). and it's possible that this disconnect is causing wrong coords to be used during repaint, which could give the illusion that things aren't being repainted immediately. – jtahlborn Dec 16 '14 at 15:23
  • btw, saying "that glaring bug isn't the one i care about" when you _don't actually know_ why your code doesn't work correctly is a rather short-sighted position to take. – jtahlborn Dec 16 '14 at 15:24
  • I'm sorry for my position, the fact is I don't deal with a tiny desync between graphics and physics but a huge lag of graphics refreshing, unless I move my mouse over the window, which is super strange btw. I'm totally open about any solution for my issue, but instead of telling me I don't do things correctly, could you please tell me how to do properly and then I will test if that's a correct solution and feedback to you ? – Coukaratcha Dec 16 '14 at 17:31

0 Answers0