Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

List in JScrollPane painting outside the viewport

I have a list, each item of which has several things in it, including a JProgressBar which can be updated a lot. Each time one of the items updates its JProgressBar, the ListDataListener on the list tries to scroll it to the visible range using

/*
 * This makes the updating content item automatically scroll
 * into view if it is off the viewport.
 */
public void contentsChanged(final ListDataEvent evt) {
    if (!EventQueue.isDispatchThread()) {
        /**
          * Make sure the scrolling happens in the graphics "dispatch" thread.
          */
        EventQueue.invokeLater(new Runnable() {
            public void run()  {
               contentsChanged(evt);
            }
        });
    }
    if (playbackInProgress) {
        int index = evt.getIndex0();
        currentContentList.ensureIndexIsVisible(index);
    }
}

Note that I'm trying to make sure the scrolling is done in the dispatch thread, since I thought maybe the problem was it being scrolled while it was repainting. And yet, I still have a problem where if things are really active, some of the list items paint outside of the viewport, overwriting what's outside the JScrollPane. Forcing an exposure event will repaint those things, but it's annoying.

Is there anything else I need to look out for to stop these things painting outside of their clipping area?

like image 540
Paul Tomblin Avatar asked Dec 15 '25 21:12

Paul Tomblin


1 Answers

Have you tried explicitly enabling double-buffering on the JList and/or the components that it is drawing over? (with:setDoubleBuffered(boolean aFlag))

Another thought is that you might need to exit the function immediately after delegating to the EDT. The way your code is written, it looks like the update will happen in both threads if ContentChanged is invoked from a non-EDT thread. Logging in the first if (or set a breakpoint in the if -- but not in the runnable -- should help determine if that is your problem.

eg:

public void contentsChanged(final ListDataEvent evt)
{
    if (!EventQueue.isDispatchThread())
    {
        log.debug("Delegating contentsChanged(...) to EDT");

        EventQueue.invokeLater(new Runnable() 
        {
            public void run() 
            {
                contentsChanged(evt);
            }
        });
        // don't run ensureIndexIsVisible twice:
        return;
     }

     if (playbackInProgress)
     {
         int index = evt.getIndex0();
         currentContentList.ensureIndexIsVisible(index);
     }
}
like image 170
rcreswick Avatar answered Dec 18 '25 00:12

rcreswick



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!