我有一個class GridPanel extends JPanel
,靜態內部類ToolSelectComboBox extends JComboBox
,它又有兩個靜態內部類ToolSelectComboBoxModel implements ComboBoxModel
和ToolSelectComboBoxRenderer implements ListCellRenderer
。該面板顯示ToolSelectComboBox
(TSCB),其構造函數將其模型和渲染器設置爲我創建的自定義模型。該框已正確創建,其模型和渲染器正常工作。ImageIcon慢在ListCellRenderer
但是,渲染器的getListCellRendererComponent(...)
方法在其返回的JLabel
上使用ImageIcon
。圖標裝入正確,但是,我第一次單擊組合框(每次運行),圖像需要恰好(或至少非常非常接近)比第二多一點加載。我會認爲這是在加載文件有些滯後,但
- 這是我的本地文件系統
- 當我添加
System.out.println
命令和result.setIcon(...)
命令後,他們按照對方之前,4KB的文件幾乎立即。
,我發現奇怪的是,println
命令被解僱兩次,一旦當我點擊框,再次圖標加載時。
也可能值得注意的是,由於這是設計用於重寫父抽象類的單個方法(用於生成圖標的路徑)的多個類的工作,所以當我注意到這是工作緩慢時,我在一個TreeMap<Tool.ImageSize, ImageIcon>
(其中Tool
是我創建具有ImageIcon getIcon()
方法的接口。
所有改變了代碼從簡單地與getIcon
命令檢索圖標,存儲各種尺寸的圖標(16,32,和64像素的平方)我進口秩序。
任何幫助,將不勝感激!
我很抱歉,如果我發佈了太多的代碼,但我想確保它是可以理解的。另一方面,如果你需要了解更多的代碼,請不要猶豫,問問。
代碼(以「*
」打頭,類似於註釋文本行全部倒塌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
的抽象方法來獲得圖像路徑),而且由於該方法的工作原理(它獲取的路徑罰款,它只是加載緩慢),我沒有將這個類的圖標。
的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);
}
感謝您的回覆!你說的關於在單獨的Thread上運行的'println'命令是有道理的;我沒有想到這一點。但是,事件派發線程是什麼?維基百科的文章並沒有讓我清楚,我對Java相當陌生(並且習慣了C++,我聽說這是一個麻煩從轉移),所以請原諒我的無知:)。我認爲通過將'ImageIcon'放入我的'TreeMap'中,圖標會自動加載;情況並非如此?如果沒有,我該怎麼做? 'loadImage()'是受保護的;我應該使用'getImage()'嗎? – wchargin
我嘗試了'getImage()',並且在新的'Thread'和默認'Thread'內都出現了滯後時間。你會建議我做什麼?我應該只是創建一個圖形對象並將它繪製到圖標上? – wchargin
是創建ImageIcon應該導致圖像被加載。從你的代碼中看不出你何時或如何做到這一點。所以我不知道在創建和顯示GUI時是否這樣做,或者是否在單擊組合框時發生。它似乎是後者。 EDT是Event Dispatch Thread。 GUI的所有更新都應在此主題上執行。閱讀[併發中的Swing](http://download.oracle.com/javase/tutorial/uiswing/concurrency/index.html)瞭解更多信息。我包含了我的SSCCE,可以在預加載時立即顯示圖標。 – camickr