Reputation:
I'm trying to use animated (GIF) icons in a JComboBox.
As the DefaultListCellRenderer is based on JLabel, ImageIcons are directly supported when putting them into the the ComboBoxModel.
However this does not work with animated GIFs.
In the dropdown they are not show at all unless they are selected (the GIFs do work when used in a regular JLabel though)
The code to populate the combobox is straight forward:
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 is the static one and is shown without any problems. The others are animated. (The images are loaded correctly because if I assign any of those icons to a JLabel directly they are displayed just fine)
I also tried to use my own ListCellRenderer based on a JPanel (inspired by the answer to this question: Java animated GIF without using a JLabel).
That works a bit better but not ideal either. The icons are only shown if I move the mouse over them while the dropdown is shown. So I guess it's a repaiting issue, although I don't know where
This is the part from my JPanel that implements the ListCellRenderer interface.
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;
}
The call to revalidate() and repaint() was inspired by looking at the code of JLabel.setIcon()
The paint() method is straight forward as well:
public void paintComponent(Graphics g)
{
super.paintComponent(g);
if (image != null)
{
g.drawImage(image, 0, 0, this);
}
}
Any ideas? I don't really need those icons to be animated in the dropdown (although that would be nice) but I would at least like to see the static images.
Upvotes: 2
Views: 1265
Reputation: 9808
This example was inspired from 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);
}
}
Upvotes: 2