Список в JScrollPane, отображаемый за пределами области просмотра
-
09-06-2019 - |
Вопрос
У меня есть список, каждый элемент которого содержит несколько элементов, включая JProgressBar
который может быть часто обновлен.Каждый раз, когда один из элементов обновляет свой JProgressBar
, тот самый ListDataListener
в списке пытается прокрутить его до видимого диапазона, используя
/*
* 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);
}
}
Обратите внимание, что я пытаюсь убедиться, что прокрутка выполняется в потоке отправки, поскольку я подумал, что, возможно, проблема в том, что он прокручивается во время перерисовки.И все же, у меня все еще есть проблема, когда, если объекты действительно активны, некоторые элементы списка отображаются за пределами области просмотра, перезаписывая то, что находится за пределами JScrollPane
.Принудительное выполнение события экспозиции приведет к перерисовке этих объектов, но это раздражает.
Есть ли что-нибудь еще, на что мне нужно обратить внимание, чтобы остановить рисование этих предметов за пределами области их обрезки?
Решение
Вы пробовали явно включить двойную буферизацию в JList и / или компонентах, на которые он накладывается?(с:setDoubleBuffered(boolean aFlag)
)
Другая мысль заключается в том, что вы мог бы необходимо выйти из функции сразу после делегирования ее EDT.Судя по тому, как написан ваш код, похоже, что обновление произойдет в обоих потоках, если ContentChanged
вызывается из потока, отличного от EDT.Вход в систему первый if
(или установите точку останова в if - но нет в runnable - должно помочь определить, является ли это вашей проблемой.
например:
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);
}
}