2012-04-07 54 views
3

我有一個簡單的Swing Java應用程序執行搜索,結果顯示在一個新選項卡中。搜索正在運行時,我想在標籤的標題中顯示進度圖標或動畫。我嘗試添加一個gif圖標,但它不生成動畫。有沒有理由爲什麼這不起作用?JTabbedPane:在選項卡中顯示任務進度

+0

這樣做的「最驚喜的路」將是A'JProgressBar'感興趣的標籤,或共同進步的組件之間欄(在選項卡窗格外部),顯示所選選項卡的進度。 *「任何建議?tnx」* 1)不要這樣做。 2)拼寫正確的單詞,比如「謝謝」,或者更好,將它們排除在外 - 它們是噪音。 – 2012-04-07 14:47:38

+0

謝謝,但我想實現類似Firefox的選項卡(帶有顯示加載進度的圖標)。 – Paco 2012-04-07 15:02:05

+1

好吧,亞克,但'我們有技術',所以看到我的答案。作爲練習,讀者可以選擇顏色(和圖像樣式等),看起來不像他們被癡呆的黑猩猩想象。 – 2012-04-07 15:22:51

回答

11

Swing tutorial about progress bars(並顯示一般進展)是一個非常好的開始。它向您展示瞭如何通過使用SwingWorker在工作線程上執行持久操作,並以特定間隔更新您的UI以向用戶顯示持久操作的進度。有另一個教程可用於獲取更多信息SwingWorker and concurrency in Swing

和往常一樣,本網站充滿了實例。例如a previous answer of mine使用SwingWorker類顯示進度用戶

編輯

正如我錯過了標題你的問題的標籤一部分。您可以創建一個「進度圖標」並在選項卡上進行設置。 SwingWorker然後可以用來更新圖標。

這樣的圖標的一個例子是example progress icon,它基本上是您每次進行一些進度時旋轉的圖像。該tabbed pane tutorial展示瞭如何將圖標添加到您的標籤(甚至可以使用自定義組件)

EDIT2

,因爲它似乎我的Mac結合JDK1.7使得它更容易顯示GIF動畫,然後在其他系統上,我也創建了一個小型SSCCE,與Andrew非常相似,但帶有旋轉圖標,看起來不像它是由創建的,我引用'瘋狂的黑猩猩'。旋轉圖標代碼來自this site(我使用了一個精簡版本並添加了定時器)。只有我不太滿意的事實是我需要將我的選項卡窗格傳遞給旋轉圖標才能觸發。可能的解決方案是將計時器拉到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 screenshot

+0

這一切都很好,但OP希望在*選項卡本身*中顯示進度。我沒有看到你的答案涉及這部分。 – 2012-04-07 14:44:37

+0

哦,我沒有看到tab_部分的_title,只是他正在使用選項卡窗格。那確實這不是一個答案。將看看我是否可以添加一些有用的回覆,或刪除它,否則 – Robin 2012-04-07 14:47:52

+0

感謝您的答案,但在我的情況下,我不能使用此方法:程序無法訪問搜索進度(由服務器執行)。所以我必須顯示一個進度圖標,並且只有當我收到來自服務器的響應時才隱藏它。 – Paco 2012-04-07 15:06:27

7

Animated image as tab icon

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(); 
      } 
     }); 
    } 
} 
+3

非常好!另請參閱此相關的[示例](http://stackoverflow.com/a/3484251/230513)。 – trashgod 2012-04-07 17:17:09

+1

@trashgod Jeesh ..我應該知道a)你已經有了這樣一個例子b)與那些可愛的Mac之一。屏幕截圖。c)我已經投了票,d)這比我在幾個'瘋狂'時刻可以攻破的任何東西都要好! (除非我仍然喜歡這個事實,我的方法不需要重寫任何東西,不確定這是否構成這種情況下的「優秀設計」,或者僅僅是「鞭a一匹死馬」。) – 2012-04-07 17:27:43

+2

我認爲這兩者在所有計數上都是互補的;引用。 – trashgod 2012-04-07 19:58:42

4

@Andrew湯普森

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是好,becasue Sn'Oracle刪除重要方法==我的看法)

4),你必須force ..... for Swing JComponents by @aterai

5)Rob's Animated Icon分幾次支持文件檔案羅布對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; 
     } 
    } 
} 
+2

在'ColorPanel'中作爲'JLabel'添加時也可以使用。 – trashgod 2012-04-09 09:52:43

+1

感謝您重新解決此問題。 +1 :) – 2012-04-09 12:50:20

相關問題