呈现JList时更改光标 [英] Changing cursor when rendering a JList
问题描述
我已经实现了我想做的事情,但是我不禁想到有一种更有效的方法……让我举例说明.
I've achieved what I'm trying to do, but I can't help but to think there is a more efficient way...allow me to illustrate.
简而言之,我要问的问题是,是否有一种方法可以确定组件何时完成其初始渲染.
In short, the question I'm asking is if there's a way to determine when a component has finished it's initial rendering.
我有一个JList,它连接到DefaultListModel并由扩展DefaultListCellRenderer的自定义渲染器绘制.
I have a JList, which is hooked up to a DefaultListModel and getting painted by a custom renderer which extends the DefaultListCellRenderer.
JList的目的是通过日志文件分页",每次加载新页面时,将填充2500个元素.在我的机器上,通常需要花费几秒钟来完全呈现JList,这并不是一个真正的问题,因为将光标更改为等待光标是可以接受的,因为它将立即为用户提供反馈.不幸的是,我无法找到一种优雅的方式来知道初始渲染何时完成.
This intention of the JList is to "page" through a log file, populating 2500 elements every time a new page is loaded. On my machine it usually takes a couple seconds to fully render the JList, which is not really a problem because changing the cursor to a wait cursor would be acceptable because it would give the user immediate feedback. Unfortunately, I cannot figure out an elegant way to know when the initial rendering has completed.
下面是渲染器的代码,在其中,您将看到我正在计算渲染器上的迭代次数.如果介于0到N-20之间,则光标变为等待光标.到达N-20后,它将恢复为默认光标.就像我之前提到的那样,这很好用,但是该解决方案确实感觉像是黑客.我已经实现了DefaultListModel的ListDataListener和JList的PropertyChangeListener,但是都没有实现我想要的功能.
Below is the code of my renderer, in it you'll see I'm counting the number of iterations on the renderer. If that is between 0 and N-20, the cursor changes to a wait cursor. Once N-20 has been reached, it reverts back to a default cursor. Like I previously mentioned, this works just fine, but the solution really feels like a hack. I've implemented the ListDataListener of the DefaultListModel and the PropertyChangeListener of the JList, but neither produce the functionality I'm looking for.
/**
* 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));
推荐答案
1),您已经将Cursor
添加到JList
,而不是在Renderer
内部,例如此处
1) you have add Cursor
to the JList
, not inside Renderer
, example here or here
2)默认情况下,Renderer
返回JLabel
,没有特殊的理由来定义
2) Renderer
by default returns JLabel
, there isn't special reason for defining that
3)Renderer
可以setBackground
,Font
(在这种情况下)JLabel
3) Renderer
can setBackground
, Font
whatever methods for (in this case) the JLabel
4)删除retVal.setText(formatListBoxOutput((String)value, index));
创建DefaulListModel并将准备好的项目移至Model#addItem
4) remove retVal.setText(formatListBoxOutput((String)value, index));
create DefaulListModel and move prepared Items to the Model#addItem
5)int index,
可以与JList#getModel().getSize() -1;
进行比较,将其从Renderer中删除,
5) int index,
can compare with JList#getModel().getSize() -1;
remove that from Renderer,
6)最好是从BackGround Task添加项目(@trashgod,您的建议是正确的:-)并填写批次(谢谢),如果您要实现SwingWorker,则可以在50个Items上创建批次并添加50 ...直到完成
6) better would be add your Items from BackGround Task (@trashgod your suggestion was right:-) and fill in batches (thank you), if you'll implemnts SwingWorker, then you can create batch at 50 Items and adding by 50... until done
7)渲染器仅用于格式化输出,您的HTML格式化可能是:
7) Renderer is only for formating output, your Html formating could be:
- 已移除,其余请参阅第3点.
- 是在BackGroung任务中准备的,而不是在Renderer和加载之间进行构建的构造函数,并且+ html格式+向Renderer的向后交互,在这种情况下,Renderer没用,因为您可以使用Html预先格式化项目,然后删除Renderer.
这篇关于呈现JList时更改光标的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!