JTabbedPane: mostra o progresso da tarefa em uma guia

Eu tenho um aplicativo Swing Java simples que realiza pesquisas e os resultados são mostrados em uma nova guia. Enquanto a pesquisa está em execução, quero mostrar um ícone ou animação de progresso no título da guia. Eu tentei adicionar um ícone de gif, mas ele não anima. Existe uma razão pela qual isso não está funcionando?

O tutorial do Swing sobre as barras de progresso (e mostrando o progresso em geral) é um ótimo lugar para começar. Ele mostra como executar operações de longa duração em um thread de trabalho usando um SwingWorker e atualizando sua interface do usuário em determinados intervalos para mostrar o progresso da operação de longa duração para o usuário. Há outro tutorial disponível para mais informações sobre o SwingWorker e a simultaneidade no Swing

E como sempre, este site está repleto de exemplos. Por exemplo, uma resposta anterior minha usa a class SwingWorker para mostrar o progresso para um usuário

Editar

Como eu perdi o título de guia parte da sua pergunta. Você pode criar um “ícone de progresso” e definir isso na guia. O SwingWorker pode então ser usado para atualizar o ícone.

Um exemplo de tal ícone é ícone de progresso de exemplo , que é basicamente uma imagem que você roda cada vez que algum progresso é feito. O tutorial do painel com guias mostra como adicionar icons às suas guias (ou até mesmo usar componentes personalizados)

Edit2

Como parece que o meu Mac em combinação com o JDK1.7 torna muito mais fácil mostrar um gif animado em outros sistemas, criei também um pequeno SSCCE, bastante semelhante ao de Andrew, mas com um ícone rotativo que não parece foi criado e cito “Chimpanzee demente”. O código de ícone rotativo vem deste site (usei uma versão simplificada e adicionei o timer). A única coisa que eu não estou muito feliz é o fato de que eu preciso passar meu painel com guias para o ícone rotativo para acionar. A solução possível é puxar o timer para fora da class RotatingIcon , mas, ei, é apenas um SSCCE. As imagens não estão incluídas, mas foram encontradas no Google.

 import javax.swing.Icon; import javax.swing.ImageIcon; import javax.swing.JComponent; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JTabbedPane; import javax.swing.Timer; import java.awt.Component; import java.awt.EventQueue; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.Rectangle; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.geom.AffineTransform; public class ProgressTabbedPane { public static void main( String[] args ) { EventQueue.invokeLater( new Runnable() { @Override public void run() { JFrame frame = new JFrame( "RotatingIcon" ); JTabbedPane tabbedPane = new JTabbedPane( ); tabbedPane.addTab( "Searching", new RotatingIcon( new ImageIcon( "resources/images/progress-indeterminate.png" ), tabbedPane ), new JLabel( new ImageIcon( "resources/images/rotatingIcon.gif" ) ) ); frame.getContentPane().add( tabbedPane ); frame.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE ); frame.pack(); frame.setVisible( true ); } } ); } private static class RotatingIcon implements Icon{ private final Icon delegateIcon; private double angleInDegrees = 90; private final Timer rotatingTimer; private RotatingIcon( Icon icon, final JComponent component ) { delegateIcon = icon; rotatingTimer = new Timer( 100, new ActionListener() { @Override public void actionPerformed( ActionEvent e ) { angleInDegrees = angleInDegrees + 10; if ( angleInDegrees == 360 ){ angleInDegrees = 0; } component.repaint(); } } ); rotatingTimer.setRepeats( false ); rotatingTimer.start(); } @Override public void paintIcon( Component c, Graphics g, int x, int y ) { rotatingTimer.stop(); Graphics2D g2 = (Graphics2D )g.create(); int cWidth = delegateIcon.getIconWidth() / 2; int cHeight = delegateIcon.getIconHeight() / 2; Rectangle r = new Rectangle(x, y, delegateIcon.getIconWidth(), delegateIcon.getIconHeight()); g2.setClip(r); AffineTransform original = g2.getTransform(); AffineTransform at = new AffineTransform(); at.concatenate(original); at.rotate(Math.toRadians( angleInDegrees ), x + cWidth, y + cHeight); g2.setTransform(at); delegateIcon.paintIcon(c, g2, x, y); g2.setTransform(original); rotatingTimer.start(); } @Override public int getIconWidth() { return delegateIcon.getIconWidth(); } @Override public int getIconHeight() { return delegateIcon.getIconHeight(); } } } 

Uma captura de canvas para referência. Uma pena que os icons não rodem na imagem. Captura de tela do SSCCE

Imagem animada como ícone de guia

 import javax.swing.*; import java.awt.*; import java.awt.event.*; import java.awt.image.*; public class ImageOnTab { ImageOnTab() { final BufferedImage image = new BufferedImage( 32,32,BufferedImage.TYPE_INT_RGB); final JTabbedPane pane = new JTabbedPane(); ImageIcon icon = new ImageIcon(image); pane.addTab( "Progress", icon, new JTree() ); ActionListener listener = new ActionListener() { int x = 0; int step = 1; public void actionPerformed(ActionEvent ae) { Graphics g = image.createGraphics(); x+=step; if (step>0) { if (x>32) { step=-step; } } else if (x<0) { step=-step; } g.setColor(Color.ORANGE); g.fillRect(0,0,32,32); g.setColor(Color.RED); g.fillRect(0,0,x,32); g.dispose(); pane.repaint(); } }; Timer timer = new Timer(100,listener); timer.start(); JOptionPane.showMessageDialog(null, pane); } public static void main(String[] args) throws Exception { //Create the GUI on the event dispatching thread SwingUtilities.invokeLater(new Runnable(){ @Override public void run() { new ImageOnTab(); } }); } } 

@Andrew Thompson

 It would be great if the J2SE supported animated GIFs 'out of the box' in more situations. I tried that animated GIF (nice image, BTW) as a tab icon, and no, it remains static. 

Eu não quero ler tudo …, mas junte o código pelo seu e majestade do @ trashgod

1) use Htlm (não sou bom em HTML puro)

2) use GlassPane com JLabel#(setOpaque(true))

3) use o JLayer (o JXLayer é melhor, porque o Sn’Oracle remove methods importantes == meu ponto de vista)

4) você tem que forçar ….. para Swing JComponents by @aterai

5) Rob’s Animated Icon algumas vezes metioned suporte por Rob para JTabbedPane

código

 import java.awt.*; import java.awt.event.*; import java.net.MalformedURLException; import java.net.URL; import java.util.Random; import java.util.logging.Level; import java.util.logging.Logger; import javax.swing.*; //https://stackoverflow.com/questions/3483485/java-jprogressbar-or-equivalent-in-a-jtabbedpane-tab-title/3484251#3484251 public class JTabbedTest { private JFrame f = new JFrame(); private JTabbedPane jtp = new JTabbedPane(); private URL url = null; public JTabbedTest() { try { url = new URL("http://pscode.org/media/starzoom-thumb.gif"); } catch (MalformedURLException ex) { Logger.getLogger(JTabbedTest.class.getName()).log(Level.SEVERE, null, ex); } ImageIcon ii = new ImageIcon(url); f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); jtp.setPreferredSize(new Dimension(400, 200)); createTab("Reds", Color.RED); createTab("Greens", Color.GREEN); createTab("Blues", Color.BLUE); f.add(jtp, BorderLayout.CENTER); jtp.setTitleAt(2, ""); // change foreground Color for disabled tab /*jtp.setTitleAt(2, "" + jtp.getTitleAt(2) + "");*/ Rectangle tabBounds = jtp.getBoundsAt(0); Container glassPane = (Container) f.getRootPane().getGlassPane(); glassPane.setVisible(true); glassPane.setLayout(new GridBagLayout()); GridBagConstraints gbc = new GridBagConstraints(); gbc.weightx = 1.0; gbc.weighty = 1.0; gbc.fill = GridBagConstraints.NONE; gbc.insets = new Insets(tabBounds.y + 23, 0, 0, 5); gbc.anchor = GridBagConstraints.NORTHEAST; JButton button = new JButton("My Button Position", ii); button.setPreferredSize(new Dimension(button.getPreferredSize().width, (int) tabBounds.getHeight() - 2)); glassPane.add(button, gbc); f.pack(); f.setVisible(true); } private void createTab(String name, Color color) { ProgressIcon icon = new ProgressIcon(color); jtp.addTab(name, icon, new ColorPanel(jtp, icon)); } public static void main(String[] args) { EventQueue.invokeLater(new Runnable() { @Override public void run() { JTabbedTest jTabbedTest = new JTabbedTest(); } }); } private static class ColorPanel extends JPanel implements ActionListener { private static final Random rnd = new Random(); private static final long serialVersionUID = 1L; private final Timer timer = new Timer(1000, this); private final JLabel label = new JLabel("Stackoverflow!"); private final JTabbedPane parent; private final ProgressIcon icon; private final int mask; private int count; public ColorPanel(JTabbedPane parent, ProgressIcon icon) { super(true); this.parent = parent; this.icon = icon; this.mask = icon.color.getRGB(); this.setBackground(icon.color); label.setForeground(icon.color); this.add(label); timer.start(); } @Override public void actionPerformed(ActionEvent e) { this.setBackground(new Color(rnd.nextInt() & mask)); this.icon.update(count += rnd.nextInt(8)); this.parent.repaint(); } } private static class ProgressIcon implements Icon { private static final int H = 16; private static final int W = 3 * H; private Color color; private int w; public ProgressIcon(Color color) { this.color = color; } public void update(int i) { w = i % W; } @Override public void paintIcon(Component c, Graphics g, int x, int y) { g.setColor(color); g.fillRect(x, y, w, H); } @Override public int getIconWidth() { return W; } @Override public int getIconHeight() { return H; } } }