我有一个class GridPanel extends JPanel
,有一个静态内部类ToolSelectComboBox extends JComboBox
,后者又有两个静态内部类ToolSelectComboBoxModel implements ComboBoxModel
和ToolSelectComboBoxRenderer implements ListCellRenderer
。该面板显示ToolSelectComboBox
(TSCB),其构造函数将其模型和渲染器设置为我创建的自定义模型。该框已正确创建,其模型和渲染器可正常工作。
但是,渲染器的getListCellRendererComponent(...)
方法在其返回的ImageIcon
上使用JLabel
。图标已正确加载,但是,当我第一次单击组合框时(每次运行),图像将完全(或至少非常非常接近)加载一秒钟以上加载。我认为这是加载文件时的一些延迟,除了
System.out.println
命令之前和之后添加result.setIcon(...)
命令时,它们几乎立即相互跟随。我注意到的一件奇怪的事情是println
命令被激活两次,一次是我点击框,一次是当图标加载时。
值得注意的是,因为它设计用于覆盖父抽象类的单个方法的多个类(以生成图标的路径),当我注意到这工作缓慢时,我改变了代码只需使用getIcon
命令检索图标,即可在TreeMap<Tool.ImageSize, ImageIcon>
中存储各种大小的图标(16,32和64像素平方)(其中Tool
是我创建的界面它有一个ImageIcon getIcon()
方法。
我的所有进口都是有序的。
任何帮助将不胜感激!
如果我发布了太多代码,我很抱歉,但我想确保它是可以理解的。另一方面,如果您需要更多代码供您理解,请不要犹豫。
代码(以“*
”开头且具有类似注释的文本的所有行都是折叠的JavaDoc标记,而不仅仅是混乱的代码):
public class GridPanel extends JPanel {
public static class ToolSelectComboBox extends JComboBox {
// Combo box model `ToolSelectComboBoxModel` snipped
* A renderer for the {@link ToolSelectComboBoxModel}. This may
public static class ToolSelectComboBoxRenderer implements
ListCellRenderer {
* The default renderer. Only the icon and text are modified.
protected DefaultListCellRenderer d = new DefaultListCellRenderer();
@Override
public Component getListCellRendererComponent(final JList list,
final Object value, final int index,
final boolean isSelected, final boolean cellHasFocus) {
if (!ToolSelectComboBoxModel.class.isInstance(list.getModel())) {
throw new IllegalStateException(
"Cannot use a ToolSelectComboBoxRenderer on any list model type other than ToolSelectComboBoxModel.");
}
final JLabel result = (JLabel) d.getListCellRendererComponent(
list, value, index, isSelected, cellHasFocus);
result.setText(null);
if (value != null) {
result.setIcon(((Tool) value)
.getIcon(Tool.IconSize.SIZE_32PX));
}
return result;
}
}
public ToolSelectComboBox() {
setModel(new ToolSelectComboBoxModel());
((ToolSelectComboBoxModel) getModel()).add(new CircleTool()); // shown below
setRenderer(new ToolSelectComboBoxRenderer());
}
}
* Create the panel.
public GridPanel() {
setLayout(new BorderLayout(0, 0));
final ToolSelectComboBox toolSelectComboBox = new ToolSelectComboBox();
add(toolSelectComboBox, BorderLayout.NORTH);
final SquareGrid squareGrid = new SquareGrid(); // another class; this works fine
add(squareGrid, BorderLayout.CENTER); // irrelevant to problem
}
}
CircleTool
类只有一个方法(覆盖AbstractTool
的抽象方法来获取图像 path ),因为该方法有效(它获取路径)很好,它只是缓慢加载的图标),我没有包括这个类。
AbstractTool
类:
public abstract class AbstractTool implements Tool {
/**
* A {@link TreeMap} to map the icon sizes to their icons.
*/
protected final TreeMap<Tool.IconSize, ImageIcon> map = new TreeMap<Tool.IconSize, ImageIcon>();
/**
* Constructs the tool and sets up the {@linkplain #map}.
*/
public AbstractTool() {
for (final Tool.IconSize size : Tool.IconSize.values()) {
System.out.println("Putting value for " + size);
map.put(size,
new ImageIcon(Tool.class.getResource(getImagePath(size))));
}
}
@Override
public ImageIcon getIcon(final IconSize size) {
return map.get(size);
}
/**
* Gets the image path for the given image size.
*
* @param size
* the size
* @return the image path
*/
protected abstract String getImagePath(Tool.IconSize size);
}
答案 0 :(得分:3)
但是,我第一次单击组合框(每次运行时),图像需要一点多秒才能加载。我认为加载文件时存在一些延迟
这也是我的猜测。
除了在result.setIcon(...)命令之前和之后添加System.out.println命令时,它们几乎立即相互跟随
单击组合框时,所有代码都在EDT上运行,这意味着每个图标将按顺序加载。
但是,System.out.println()在单独的Thread上运行,因此会立即显示。
解决方案是在程序启动时加载图标。也就是说,无论何时定义/添加图标到地图,您都应该在那时阅读它们。您可能希望在单独的线程上执行此操作,因此您不会阻止GUI显示。
编辑:
这是一个简单的SSCCE,它在组合框中显示图标:
import java.awt.*;
import javax.swing.*;
public class ComboBoxIcon extends JFrame
{
JComboBox comboBox;
public ComboBoxIcon()
{
Object[] items =
{
new ImageIcon("about16.gif"),
new ImageIcon("add16.gif"),
new ImageIcon("copy16.gif")
};
comboBox = new JComboBox( items );
getContentPane().add( comboBox, BorderLayout.NORTH );
}
public static void main(String[] args)
{
JFrame frame = new ComboBoxIcon();
frame.setDefaultCloseOperation( EXIT_ON_CLOSE );
frame.pack();
frame.setLocationRelativeTo( null );
frame.setVisible( true );
}
}
如果您需要更多帮助,则需要发布展示问题的SSCCE。