JTabbedPane:在选项卡中显示任务进度

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

关于进度条的Swing教程 (以及一般的进度)是一个非常好的起点。 它向您展示了如何使用SwingWorker在工作线程上执行持久操作,并以特定间隔更新UI以向用户显示持久操作的进度。 还有另一个教程可用于有关SwingWorker和Swing中的并发性的更多信息

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

编辑

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

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

EDIT2

因为看起来我的Mac与JDK1.7相结合使得在其他系统上显示动画gif变得容易得多,我创建了一个小型SSCCE,与安德鲁的SSCCE非常相似但是带有一个看起来不像它的旋转图标我引用了’疯狂的黑猩猩’。 旋转的图标代码来自这个网站 (我使用了一个精简版本并添加了计时器)。 我唯一不高兴的是我需要将选项卡式窗格传递给旋转图标才能触发。 可能的解决办法是将计时器拉到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截图

动画图像作为选项卡图标

 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. 

我不想读整篇….但是把你的代码和@ trashgod陛下放在一起

1)使用Htlm (我在普通的Html中表现不佳)

2)使用GlassPaneJLabel#(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, ""); // 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; } } }