如何防止 JComboBox 在使用自定义 ListCellRenderer 时变得无响应
我正在使用 JComboBox
和自定义 ListCellRenderer
制作字体选择器。我想 JComboBox
显示所有可用字体,每个字体名称都以其自己的字体显示。我目前使用大约 500 种字体。
提供此功能的 ListCellRenerer
示例:
private class ComboBoxRenderer extends JLabel implements ListCellRenderer {
private JLabel label = new JLabel("Test");
@Override
public Component getListCellRendererComponent(JList list, Object value,
int index, boolean isSelected, boolean cellHasFocus) {
Font tempFont = label.getFont();
setFont(new Font((String) value, tempFont.getStyle(),
tempFont.getSize()));
setText((String) value);
return this;
}
}
问题是,使用此呈现器时,JComboBox
在程序执行期间变得无响应。第一次单击组合框以显示列表时,加载列表需要几秒钟的时间。第二次点击时,列表会立即显示。
如果有人评论这一行
setFont(new Font((String) value, tempFont.getStyle(),tempFont.getSize()));
,组合框就可以正常工作。
如何防止这种无反应现象呢?
I am making a font chooser using JComboBox
and a custom ListCellRenderer
. I want
the JComboBox
to display all available fonts, with each font name displayed in its own font. I am currently using around 500 fonts.
An example of a ListCellRenerer
that provides this functionality:
private class ComboBoxRenderer extends JLabel implements ListCellRenderer {
private JLabel label = new JLabel("Test");
@Override
public Component getListCellRendererComponent(JList list, Object value,
int index, boolean isSelected, boolean cellHasFocus) {
Font tempFont = label.getFont();
setFont(new Font((String) value, tempFont.getStyle(),
tempFont.getSize()));
setText((String) value);
return this;
}
}
The problem is that, when using this renderer, the JComboBox
becomes unresponsive during program execution. The first time one clicks on the combobox to reveal the list, it takes a couple of seconds for the list to load. The second time one clicks, the list is instantly displayed.
If one comments the line
setFont(new Font((String) value, tempFont.getStyle(),tempFont.getSize()));
, the combobox works just fine.
How can one prevent this unresponsiveness?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
所发生的情况是组合的内部尝试动态地找到首选大小。为此,它循环遍历列表中的所有项目,向渲染器提供项目以测量渲染组件的首选大小。
您可以通过设置用于测量的原型值来防止这种情况,然后使用该原型测量一次大小
编辑:正如@Boro检测到的那样,这还不够 - 它仅为组合框本身设置原型,而不为弹出窗口中的列表设置原型(如应该的,那是多么疯狂的越野车……可能是)。为了解决这个问题,我们必须手动设置它,这是一个使用
Custom ListCellRenderer 的代码片段(稍作更改,以期望 Font 类型的项目)
What happens is that the combo's internals try to find the preferred size dynamically. For doing so, it loops through all items in the list, feeds the renderer with the items to measure the rendering component's preferred size.
You can prevent that by setting a prototypeValue for measuring, then the size is measured once using that prototype
Edit: as @Boro detected, that's not enough - it sets the prototype for the comboBox itself only, not for the list in the popup (as it should, how crazily buggy can that ... possibly be). To hack around, we have to manually set it, here's a code snippet to play with
Custom ListCellRenderer (slightly changed, to expect items of type Font)
@kleopatra 比你注意到我,但
setPrototypeDisplayValue
看起来像是懒惰的选择,我的修正@kleopatra than you for notice me but
setPrototypeDisplayValue
look like as lazy choise, my amedment