2011-09-11 5 views
2

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

ただし、レンダラーのgetListCellRendererComponent(...)メソッドは、返されるJLabelImageIconを使用します。アイコンは正しくロードされますが、最初にコンボボックスをクリックすると、が正確に(または少なくとも非常に近くに)より少し遅れて読み込まれます。私はresult.setIcon(...)コマンドの前と後のSystem.out.printlnコマンドを追加すると、彼らはお互いに従ってください

  • 私のローカルファイルシステムにその

    • 除いそれは4kBのファイルで、このファイルのロード中にいくつかの遅れであることを前提としていますほぼ即座に。私は気づく

    奇妙なことはprintlnコマンドは二回、かつて私は再びボックスをクリックし、アイコンの負荷を解雇されていることです。

    親抽象クラスの単一のメソッドをオーバーライドする複数のクラスで動作するように設計されているので(iconへのパスを生成するために)、これがゆっくりと動作していることに気付いたとき、 TreeMap<Tool.ImageSize, ImageIcon>Tool私はそれがImageIcon getIcon()方法を有し作成インタフェースである。

    すべてに単にgetIconコマンドでアイコンを検索から様々なサイズのアイコン格納するコードを変更した(16、32、及び64 PXは二乗)私の輸入品は順番にあります。

    何か助けていただければ幸いです!

    あまりにも多くのコードを投稿した場合はお詫び申し上げますが、わかりやすくしたいと思っていました。一方、理解するためにより多くのコードが必要な場合は、お気軽にお問い合わせください。

    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クラスが唯一持っている一つの方法(オーバーライドへ:

    コード(コメントのようなテキストを「*」で始まり、持っているすべての行は、Javadocタグだけでなく、めちゃめちゃアップコードを折りたたまれ) 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); 
    
    } 
    
  • 答えて

    3

    しかし、私は(各実行上の)コンボボックスをクリックしてください最初の時間は、画像をロードするために、第2のより少しかかります。私はこれがファイルの読み込みにある程度遅れていると仮定します。

    それは私の推測でもあります。ことを除いて

    私はのSystem.out.printlnは前にコマンドやコンボボックスをクリックするとresult.setIcon(...)コマンドの後、彼らはほぼ瞬時に

    互いに続く追加すべてのコードは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を投稿する必要があります。

    +0

    お返事ありがとうございます!別のスレッドで実行されている 'println'コマンドについてあなたが言っていることは意味があります。私はそれを考えなかった。しかし、イベントディスパッチスレッドは何ですか?ウィキペディアの記事は私には分かりません。私はかなりJavaに慣れていません(そしてC++には慣れていますが、これは私が聞いたことは転送の面倒です)ので、私の無知を赦してください。私は 'ImageIcon'を私の' TreeMap'に入れて、アイコンが自動的にロードされると仮定しました。これは当てはまりませんか?そうでない場合は、どうすればいいですか? 'loadImage()'は保護されています。 'getImage()'を使うべきですか? – wchargin

    +0

    私は 'getImage()'を試しましたが、新しい 'Thread'内とデフォルトの' Thread'内の両方で遅延時間がまだ発生していました。私は何を提案しますか?私はただグラフィックスオブジェクトを作成し、それにアイコンをペイントする必要がありますか? – wchargin

    +0

    はいImageIconを作成すると、画像がロードされるはずです。あなたのコードから、いつ、どのようにこれを行うのかは明らかではありません。ですから、GUIを作成して表示するとき、またはコンボボックスをクリックしたときにそれが起きるかどうかはわかりません。後者のようです。 EDTはEvent Dispatch Threadです。このスレッドでは、GUIに対するすべての更新が実行されます。詳細は、[同時実行の同時実行](http://download.oracle.com/javase/tutorial/uiswing/concurrency/index.html)を参照してください。 SSCCEには、プリロードされたときにアイコンが即座にレンダリングされることが示されています。 – camickr

    関連する問題