我已經實現了我正在嘗試做的事情,但我不禁想到有一種更高效的方式......請允許我說明。渲染JList時更改光標
總之,我問的問題是,如果有一種方法可以確定組件何時完成初始渲染。
我有一個JList,它連接到一個DefaultListModel,並通過擴展DefaultListCellRenderer的自定義渲染器進行繪製。
JList的這種意圖是通過日誌文件「頁面」,每次加載新頁面時填充2500個元素。在我的機器上,通常需要幾秒鐘才能完全呈現JList,這不是一個真正的問題,因爲將光標更改爲等待光標將是可以接受的,因爲它會給用戶提供即時反饋。不幸的是,我無法想出一個優雅的方式來知道初始渲染何時完成。
下面是我的渲染器的代碼,其中你會看到我正在計算渲染器上的迭代次數。如果在0到N-20之間,則光標變爲等待光標。一旦到達N-20,它將恢復爲默認光標。就像我之前提到的,這很好,但解決方案真的感覺像是黑客。我已經實現了DefaultListModel的ListDataListener和JList的PropertyChangeListener,但都沒有產生我正在尋找的功能。
/**
* 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));
你能否提供更多的代碼? – StanislavL
添加了更多代碼,但我不確定它是否有助於解決問題。我正在尋找的是一種確定組件是否已完成初始渲染而不實施計數器的方法。 – JoshBramlett
從來沒有(如:不不不不不,乾脆不要)在渲染改變調用列表的狀態。 getXXRendererComponent中給出的所有參數都是嚴格只讀的。別的地方移動你的邏輯@trashgod已經建議 – kleopatra