0

Alright, so I have a null layout JPanel with a single JLabel in it. The JLabel is positioned at (0,0). What I'm trying to do is use a while loop in a new Thread to sleep the new Thread and then shift the JLabel 10px down by using SwingUtilities.invokeLater . The problem is that the UI gets updated in a laggy sort of way. It doesn't update every time it should, but skips lots of updates and shifts in big chunks. I know I can easily do it with Timer, but the point is understanding Threads better. Thanks in advance!

Code:

private void start(){
    Updater up = new Updater();
    up.start();
}
public void updatePosition(){
    int y = label1.getLocation.y;
    label.setBounds(0,y+10, 10,10);
}
private class Updater extends Thread{
    public void run(){
        while(!shouldQuit){
            try{
                Updater.sleep(100);
                SwingUtilities.invokeLater(new Runnable() {
                    public void run() {
                       updatePosition(); 
                    }
                }); 
            }catch(Exception e){
                System.out.println(e);
            }      
        }   
    }
}

EDIT: I got it to work by replacing the while loop with a call to a new Thread instance in the updatePosition() method, to settle things down a bit. And also, it wasn't only the Thread that was causing the problem, so I had to force the panel to re-layout it's subviews by calling revalidate() on it. Here's how it looks (the fully working one):

private void start(){
    new Updater().start();
}
public void updatePosition(){
    int y = label1.getLocation.y;
    label.setBounds(0,y+10, 10,10);
    panel.revalidate();
    if(!shouldQuit) new Updater().start();
}
private class Updater extends Thread{
    public void run(){
        try{
            Updater.sleep(100);
            SwingUtilities.invokeLater(new Runnable() {
                public void run() {
                    updatePosition(); 
                }
            }); 
        }catch(Exception e){
            System.out.println(e);
        }   
    }
}
martin
  • 1,007
  • 2
  • 16
  • 32
  • *"How to implement a smoothly falling JLabel without using Timer, but Threads instead"* Why 'without timer'? Why also not do this in a custom painted panel, instead of trying to position a component on the fly? – Andrew Thompson Oct 10 '15 at 23:21
  • Timer is based on Threads, so I figure there should be a way to do it, and it's just a problem I don't know the solution to, so that makes it worth solving. How would you suggest I do it in a custom painted panel? – martin Oct 10 '15 at 23:29
  • 1
    *"How would you suggest I do it in a custom painted panel?"* Much like [this animation](http://stackoverflow.com/a/14575043/418556) but painting strings instead of shapes. Actually (checks) that uses a `BufferedImage` instead of a custom panel. But it's the same principal once you have a `Graphics` instance. – Andrew Thompson Oct 10 '15 at 23:48
  • Thanks a lot, I'll look into it. However, I just can't understand why the JLabel doesn't update on every updatePosition() call.... I feel like I'm missing something essential... – martin Oct 10 '15 at 23:56
  • 1
    Side note: It is good practice for your try/catch to be around your `while` loop rather than inside it. If some other code sends your Thread an interrupt, it means you're being requested to stop what you're doing. Putting the loop inside the try/catch is the easiest way to properly respond to that. – VGR Oct 11 '15 at 00:03

1 Answers1

0

You should try to use visibility and GridLayout to maximize movement. You can use a int var to count threads and reciprocate that to the label. As well, you should be using your ability o create Updaters, more and smoother. Just do the start() mwthod while trolling for threads :-)

You could have something besides an infinity call to start. I think you've lost the inheritance from the class, itself. The object label1 must ave been lost in tbe fray. If that's not it, then I'm pretty sure I'm not really able to answer this one.