4

我有一个执行搜索的简单 Swing Java 应用程序,结果显示在新选项卡中。在搜索运行时,我想在选项卡标题中显示进度图标或动画。我尝试添加一个 gif 图标,但它没有动画。这不起作用有什么原因吗?

4

3 回答 3

12

Swing 关于进度条(并显示一般进度)的教程是一个很好的起点。它向您展示了如何通过使用 a 对工作线程执行持久操作SwingWorker,并以一定的时间间隔更新您的 UI 以向用户显示持久操作的进度。还有另一个教程可用于获取有关SwingWorkerSwing 和并发的更多信息

和往常一样,这个网站充满了例子。例如,我以前的答案使用SwingWorker该类向用户显示进度

编辑

因为我错过了您问题的标签部分的标题。您可以创建一个“进度图标”并将其设置在选项卡上。然后SwingWorker可用于更新图标。

此类图标的一个示例是示例进度图标,它基本上是您每次取得一些进展时旋转的图像。选项卡式窗格教程向您展示如何将图标添加到选项卡(甚至使用自定义组件)

编辑2

看起来我的 Mac 与 JDK1.7 结合使用比在其他系统上更容易显示动画 gif,我也创建了一个小型 SSCCE,与 Andrew 的非常相似,但带有一个看起来不像的旋转图标是由“痴呆的黑猩猩”创建的,我引用它。旋转图标代码来自这个站点(我使用了精简版并添加了计时器)。唯一让我不太高兴的是我需要将选项卡式窗格传递给旋转图标才能触发。可能的解决方案是将计时器拉到RotatingIcon课堂外,但是嘿,它只是一个 SSCCE 。图片不包括在内,但通过 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();
    }
  } 
}

截图供参考。遗憾的是,屏幕截图中的图标没有旋转。 SSCCE 截图

于 2012-04-07T14:42:45.903 回答
7

动画图像作为选项卡图标

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();
            }
        });
    }
}
于 2012-04-07T15:20:57.383 回答
4

@安德鲁汤普森

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. 

我不想阅读整个......,而是将你的代码和@trashgod's majesty 放在一起

1)使用Htlm(我不擅长纯HTML)

2)GlassPane使用JLabel#(setOpaque(true))

3)使用JLayerJXLayer更好,因为Sn'Oracle删除重要方法==我的观点)

4)你必须通过@aterai强制......为Swing JComponents

5) Rob 的动画图标几次提到 Rob 支持JTabbedPane

代码

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, "<html><img src=" + ii + " width=20 height=20></img></html>");

        // change foreground Color for disabled tab        
        /*jtp.setTitleAt(2, "<html><font color=" + (jtp.isEnabledAt(2) ? "black" : "red") + ">"
                + jtp.getTitleAt(2) + "</font></html>");*/

        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;
        }
    }
}
于 2012-04-07T23:47:15.133 回答