2

class GridPanel extends JPanel静的内部クラスを持つToolSelectComboBox extends JComboBox、があり、これには2つの静的内部クラスToolSelectComboBoxModel implements ComboBoxModelとがありToolSelectComboBoxRenderer implements ListCellRendererます。パネルにはToolSelectComboBox(TSCB)が表示され、そのコンストラクターはモデルとレンダラーを私が作成したカスタムのものに設定します。ボックスは正しく作成され、そのモデルとレンダラーは正しく機能します。

ただし、レンダラーのgetListCellRendererComponent(...)メソッドは、それが返すImageIcononを使用します。JLabelアイコンは正しく読み込まれますが、(実行ごとに)コンボボックスを初めてクリックすると、画像の読み込みに1秒強かかります(または少なくとも非常に近くなります) 。これはファイルのロードに多少の遅れがあると思いますが、

  • これは私のローカルファイルシステム上の4kBファイルです
  • System.out.printlnコマンドの前後にコマンドを追加するとresult.setIcon(...)、それらはほぼ瞬時に相互に続きます。

私が気付いた奇妙なことは、printlnコマンドが2回起動されることです。1回はボックスをクリックしたとき、もう1回はアイコンが読み込まれたときです。

これは、親抽象クラスの単一のメソッドをオーバーライドする複数のクラスで動作するように設計されているため(アイコンへのパスを生成するため)、動作が遅いことに気付いたときに、コードを次のように変更したことにも注意してください。getIconさまざまなサイズのアイコン(16、32、および64ピクセルの2乗)をTreeMap<Tool.ImageSize, ImageIcon>(メソッド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

    }

}

このクラスにはメソッドが1つしかなく(の抽象メソッド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);

}
4

1 に答える 1

3

ただし、(実行ごとに)コンボボックスを初めてクリックすると、画像の読み込みに1秒強かかります。これはファイルの読み込みに多少の遅れがあると思います

それも私の推測です。

ただし、result.setIcon(...)コマンドの前後にSystem.out.printlnコマンドを追加すると、それらはほぼ瞬時に相互に追従します。

コンボボックスをクリックすると、すべてのコードがEDTで実行されます。つまり、各アイコンが順番に読み込まれます。

ただし、System.out.println()は別のスレッドで実行されるため、すぐに表示されます。

解決策は、プログラムの起動時にアイコンをロードすることです。つまり、アイコンを定義/マップに追加するときはいつでも、その時点でアイコンを読み込む必要があります。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を投稿する必要があります。

于 2011-09-11T18:53:08.870 に答える