Использование анимированного GIF в JComboBox

Я пытаюсь использовать анимированные (GIF) значки в JComboBox.

Поскольку DefaultListCellRenderer основан на JLabel, изображения ImageIcon напрямую поддерживаются при помещении их в ComboBoxModel.

Однако это не работает с анимированными GIF-файлами.

В раскрывающемся списке они вообще не отображаются, если они не выбраны (хотя GIF-файлы работают при использовании в обычном JLabel)

Код для заполнения поля со списком прост:

ImageIcon[] data = new ImageIcon[4];
data[0] = new ImageIcon("icon_one.gif");
data[1] = new ImageIcon("icon_two.gif");
data[2] = new ImageIcon("icon_three.gif");
data[3] = new ImageIcon("icon_four.gif");
ComboBoxModel model = new DefaultComboBoxModel(data);
setModel(model);

icon_one.gif является статическим и отображается без проблем. Остальные анимированы. (Изображения загружаются правильно, потому что, если я назначу любой из этих значков JLabel напрямую, они будут отображаться нормально)

Я также попытался использовать свой собственный ListCellRenderer на основе JPanel (вдохновленный ответом на этот вопрос: Java анимированный GIF без использования JLabel).

Это работает немного лучше, но тоже не идеально. Значки отображаются только в том случае, если я наведу на них указатель мыши, пока отображается раскрывающийся список. Так что я предполагаю, что это проблема перекрашивания, хотя я не знаю, где

Это часть моего JPanel, которая реализует интерфейс ListCellRenderer.

public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus)
{
  this.image = ((ImageIcon)value).getImage();
  if (isSelected)
  {
    setBackground(list.getSelectionBackground());
    setForeground(list.getSelectionForeground());
  }
  else
  {
    setBackground(list.getBackground());
    setForeground(list.getForeground());
  }
  revalidate();
  repaint();

  return this;
}

Вызов revalidate() и repaint() был вдохновлен просмотром кода JLabel.setIcon().

Метод paint() также прост:

public void paintComponent(Graphics g)
{
  super.paintComponent(g);
  if (image != null)
  {
    g.drawImage(image, 0, 0, this);
  }
}

Любые идеи? Мне действительно не нужно, чтобы эти значки были анимированы в раскрывающемся списке (хотя это было бы неплохо), но я хотел бы, по крайней мере, видеть статические изображения.


person a_horse_with_no_name    schedule 04.03.2012    source источник
comment
См. stackoverflow.com /questions/575782/ на аналогичный вопрос.   -  person JB Nizet    schedule 04.03.2012


Ответы (1)


Этот пример основан на AnimatedIconTableExample.java.

import java.awt.*;
import java.awt.image.*;
import java.net.*;
import javax.swing.*;
import javax.swing.plaf.basic.*;
class MainPanel {
  public JComponent makeUI() {
    JComboBox combo = new JComboBox();
    URL url1 = getClass().getResource("static.png");
    URL url2 = getClass().getResource("animated.gif");
    combo.setModel(new DefaultComboBoxModel(new Object[] {
      new ImageIcon(url1), makeImageIcon(url2, combo, 1)
    }));
    JPanel p = new JPanel();
    p.add(combo);
    return p;
  }
  private static ImageIcon makeImageIcon(
      URL url, final JComboBox combo, final int row) {
    ImageIcon icon = new ImageIcon(url);
    icon.setImageObserver(new ImageObserver() {
      //http://www2.gol.com/users/tame/swing/examples/SwingExamples.html
      //AnimatedIconTableExample.java
      @Override public boolean imageUpdate(
          Image img, int infoflags, int x, int y, int w, int h) {
        if(combo.isShowing() && (infoflags & (FRAMEBITS|ALLBITS)) != 0) {
          if(combo.getSelectedIndex()==row) {
            combo.repaint();
          }
          BasicComboPopup p = (BasicComboPopup)
            combo.getAccessibleContext().getAccessibleChild(0);
          JList list = p.getList();
          if(list.isShowing()) {
            list.repaint(list.getCellBounds(row, row));
          }
        }
        return (infoflags & (ALLBITS|ABORT)) == 0;
      };
    });
    return icon;
  }
  public static void main(String[] args) {
    EventQueue.invokeLater(new Runnable() {
      @Override public void run() {
        createAndShowGUI();
      }
    });
  }
  public static void createAndShowGUI() {
    JFrame f = new JFrame();
    f.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
    f.getContentPane().add(new MainPanel().makeUI());
    f.setSize(320, 240);
    f.setLocationRelativeTo(null);
    f.setVisible(true);
  }
}
person aterai    schedule 04.03.2012
comment
@mKorbel ссылается на: src/java/awt/Component.java#imageUpdate(...) - person aterai; 13.03.2012
comment
@aterai во-первых, это множество методов, реализованных в API, во-вторых, правильное использование ... - person mKorbel; 13.03.2012