【发布时间】:2011-11-26 06:34:59
【问题描述】:
我已经实现了我想要做的事情,但我不禁想到有一种更有效的方法……请允许我举例说明。
简而言之,我要问的问题是,是否有办法确定组件何时完成初始渲染。
我有一个 JList,它连接到 DefaultListModel 并由扩展 DefaultListCellRenderer 的自定义渲染器绘制。
JList 的目的是通过日志文件“分页”,每次加载新页面时填充 2500 个元素。在我的机器上,完全呈现 JList 通常需要几秒钟,这并不是一个真正的问题,因为将光标更改为等待光标是可以接受的,因为它会给用户立即反馈。不幸的是,我无法找到一种优雅的方式来了解初始渲染何时完成。
下面是我的渲染器的代码,在其中你会看到我正在计算渲染器的迭代次数。如果该值介于 0 和 N-20 之间,则光标变为等待光标。一旦达到 N-20,它就会恢复为默认光标。就像我之前提到的,这工作得很好,但这个解决方案真的感觉像是一个 hack。我已经实现了 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));
【问题讨论】:
-
添加了更多代码,但我不确定它是否有助于解决问题。我正在寻找的是一种在不实现计数器的情况下确定组件是否完成初始渲染的方法。
-
永远不要(如:nononono,根本不要)改变渲染器中调用列表的状态。 getXXRendererComponent 中给出的所有参数都是严格只读的。正如@trashgod 已经建议的那样,将您的逻辑移到其他地方
标签: java swing render jlist mouse-cursor