Я достиг того, что я пытаюсь сделать, но я не могу не думать, что есть более эффективный способ... позвольте мне проиллюстрировать.
Короче говоря, вопрос, который я задаю, заключается в том, есть ли способ определить, когда компонент завершил свой первоначальный рендеринг.
У меня есть JList, который подключен к DefaultListModel и рисуется пользовательским средством визуализации, которое расширяет DefaultListCellRenderer.
Это намерение JList состоит в том, чтобы «пролистывать» файл журнала, заполняя 2500 элементов каждый раз, когда загружается новая страница. На моей машине обычно требуется пара секунд, чтобы полностью отобразить JList, что на самом деле не является проблемой, потому что изменение курсора на курсор ожидания было бы приемлемым, поскольку это дало бы пользователю немедленную обратную связь. К сожалению, я не могу найти элегантный способ узнать, когда первоначальный рендеринг завершен.
Ниже приведен код моего рендерера, в нем вы увидите, что я подсчитываю количество итераций на рендерере. Если он находится в диапазоне от 0 до N-20, курсор изменится на курсор ожидания. После достижения N-20 он возвращается к курсору по умолчанию. Как я упоминал ранее, это прекрасно работает, но решение действительно похоже на хак. Я реализовал ListDataListener из DefaultListModel и PropertyChangeListener из JList, но ни один из них не дает той функциональности, которую я ищу.
/**
* Renders the MessageHistory List based on the search text and processed events
*/
public class MessageListRenderer extends DefaultListCellRenderer
{
private static final long serialVersionUID = 1L;
String lineCountWidth = Integer.toString(Integer.toString(m_MaxLineCount).length());
@Override
public Component getListCellRendererComponent(JList l, Object value, int index, boolean isSelected, boolean haveFocus)
{
JLabel retVal = (JLabel)super.getListCellRendererComponent(l, value, index, isSelected, haveFocus);
retVal.setText(formatListBoxOutput((String)value, index));
// initial rendering is beginning - change the cursor
if ((renderCounter == 0) && !renderCursorIsWait)
{
m_This.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
renderCursorIsWait = true;
}
// initial rendering is complete - change the cursor back
if ((renderCounter > (l.getModel().getSize() - 20)) && renderCursorIsWait)
{
m_This.setCursor(Cursor.getDefaultCursor());
renderCursorIsWait = false;
}
renderCounter++;
return retVal;
}
/**
* Adds font tags (marks as red) around all values which match the search criteria
*
* @param lineValue string to search in
* @param lineIndex line number being processed
* @return string containing the markup
*/
private String formatListBoxOutput(String lineValue, int lineIndex)
{
// Theoretically the count should never be zero or less, but this will avoid an exception just in case
if (m_MaxLineCount <= 0)
return lineValue;
String formattedLineNumber = String.format("%" + Integer.toString(Integer.toString(m_MaxLineCount).length()) + "s", m_CurrentPage.getStartLineNumber() + lineIndex) + ": ";
// We're not searching, simply return the line plus the added line number
if((m_lastSearchText == null) || m_lastSearchText.isEmpty())
return "<html><font color=\"#4682B4\">" + formattedLineNumber.replaceAll(" ", " ") + "</font>" + lineValue + "</html>";
// break up the search string by the search value in case there are multiple entries
String outText = "";
String[] listValues = lineValue.split(m_lastSearchText);
if(listValues.length > 1)
{
// HTML gets rid of the preceding whitespace, so change it to the HTML code
outText = "<html><font color=\"#4682B4\">" + formattedLineNumber.replaceAll(" ", " ") + "</font>";
for(int i = 0; i < listValues.length; i++)
{
outText += listValues[i];
if(i + 1 < listValues.length)
outText += "<font color=\"red\">" + m_lastSearchText + "</font>";
}
return outText + "</html>";
}
return "<html><font color=\"#4682B4\">" + formattedLineNumber.replaceAll(" ", " ") + "</font>" + lineValue + "</html>";
}
}
Все, что я делаю для заполнения модели, это:
// reset the rendering counter
this.renderCounter = 0;
// Reset the message history and add all new values
this.modelLogFileData.clear();
for (int i = 0; i < this.m_CurrentPage.getLines().size(); i++)
this.modelLogFileData.addElement(this.m_CurrentPage.getLines().elementAt(i));