2013-11-27 27 views
-1

我试图创建一个自定义的JProgressBar,利用JLayer类,使它可以根据具体情况不同,la this solution。问题是我想把它作为某种JComponent包装起来,因为它使它更易于管理。我会把它作为一个定制的JLayer公开,但是这个类是封闭的,所以没有做任何事情。我试过让它成为一个JComponent,但屏幕上没有任何东西(可能是因为我不知道如何制作一个包含其他组件的自定义JComponent?)。我尝试了一个JFrame,它可以工作,但大小是错误的,可能是因为进度条使用的是我制作的JFrame的布局管理器,而不是包含JFrame的布局管理器。我试过JProgressBar,它绘制,但然后我没有办法返回JLayer并保留正确的层次结构,没有额外的方法调用后,构造函数,这似乎并不优雅。通过JProgressBar与JLayer创建自定义JComponent

这里是我的示例代码,很大程度上依赖于从我挂到上面的问题代码:

public class Test { 
    public JComponent makeUI() { 
     final BoundedRangeModel model = new DefaultBoundedRangeModel(); 
     model.setValue(20); 

     final JPanel p = new JPanel(new GridLayout(4, 1, 12, 12)); 
     p.setBorder(BorderFactory.createEmptyBorder(24,24,24,24)); 

     // This does not draw 
     final ColorProgressBar pb4 = new ColorProgressBar(model); 
     p.add(pb4); 

     JPanel panel = new JPanel(new BorderLayout()); 
     panel.add(p, BorderLayout.NORTH); 
     return panel; 
    } 
    public static void main(String[] args) { 
     EventQueue.invokeLater(new Runnable() { 
      @Override public void run() { 
       createAndShowGUI(); 
      } 
     }); 
    } 
    public static void createAndShowGUI() { 
     try { 
      UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); 
     } catch(Exception e) { 
      e.printStackTrace(); 
     } 
     JFrame f = new JFrame(); 
     f.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); 
     f.getContentPane().add(new Test().makeUI()); 
     f.setSize(320, 240); 
     f.setLocationRelativeTo(null); 
     f.setVisible(true); 
    } 
} 

class ColorProgressBar extends JComponent { 
    private static final long serialVersionUID = -1265489165072929352L; 

    private BlockedColorLayerUI colorUI = new BlockedColorLayerUI(); 
    private JLayer<JProgressBar> layer; 
    private JProgressBar bar; 
    private PropertyChangeSupport supporter = new PropertyChangeSupport(new WeakReference<ColorProgressBar>(this)); 

    public ColorProgressBar(BoundedRangeModel model) { 
     bar = new JProgressBar(model); 
     layer = new JLayer<JProgressBar>(bar, colorUI); 
     this.add(layer); 
    } 

    public Color getColor() { 
     if (colorUI == null) 
      return null; 

     return colorUI.color; 
    } 

    public void setColor(Color color) { 
     Color oldColor = colorUI.color; 
     colorUI.color = color; 
     supporter.firePropertyChange("color", oldColor, color); 
    } 

    @Override 
    public void paintComponents(Graphics g) { 
     layer.paintComponents(g); 
    } 

    class BlockedColorLayerUI extends LayerUI<JProgressBar> { 
     public Color color = null; 
     private BufferedImage bi; 
     private int prevw = -1; 
     private int prevh = -1; 
     @Override public void paint(Graphics g, JComponent c) { 
      if(color != null) { 
       JLayer<?> jlayer = (JLayer<?>)c; 
       JProgressBar progress = (JProgressBar)jlayer.getView(); 
       int w = progress.getSize().width; 
       int h = progress.getSize().height; 

       if(bi==null || w!=prevw || h!=prevh) { 
        bi = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB); 
       } 
       prevw = w; 
       prevh = h; 

       Graphics2D g2 = bi.createGraphics(); 
       super.paint(g2, c); 
       g2.dispose(); 

       Image image = c.createImage(
         new FilteredImageSource(bi.getSource(), 
           new ColorFilter(color))); 
       g.drawImage(image, 0, 0, c); 
      } else { 
       super.paint(g, c); 
      } 
     } 
    } 
    class ColorFilter extends RGBImageFilter { 
     Color color; 

     public ColorFilter(Color color) { 
      this.color = color; 
     } 

     @Override public int filterRGB(int x, int y, int argb) { 
      int r = (int)((argb >> 16) & 0xff); 
      int g = (int)((argb >> 8) & 0xff); 
      int b = (int)((argb  ) & 0xff); 
      return (argb & color.getRGB()) | (g<<16) | (r<<8) | (b); 
     } 
    } 
} 

任何人都知道我要去哪里错了吗?谢谢!

编辑:我已经微调了这个例子,并修改它以更好地表达我的问题。对困惑感到抱歉。

+0

为了更好地帮助越早,张贴[SSCCE(http://sscce.org/)。 –

+0

我不完全确定如何缩短它的行为并使其可诊断。如果您有任何建议,请随时分享;否则它肯定是自包含和可编译的。 – Jesse

+0

*“我不完全确定如何缩短它的长度”*对于SSCCE而言,比'short'更多。回去再读一遍。此外,WTF会'UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());'与这个问题有关?'?你应该尝试去除它。 –

回答

1

您可能需要调用super(model);p.add(pb4.layer);

import java.awt.*; 
import java.awt.event.*; 
import java.awt.image.*; 
import java.beans.*; 
import java.lang.ref.WeakReference; 
import javax.swing.*; 
import javax.swing.plaf.LayerUI; 

public class Test2 { 
    public JComponent makeUI() { 
     final BoundedRangeModel model = new DefaultBoundedRangeModel(); 
     final JPanel p = new JPanel(new GridLayout(4, 1, 12, 12)); 
     p.setBorder(BorderFactory.createEmptyBorder(24,24,24,24)); 

     final JProgressBar pb1 = new JProgressBar(model); 
     pb1.setStringPainted(true); 
     p.add(pb1); 
     final JProgressBar pb2 = new JProgressBar(model); 
     pb2.setStringPainted(true); 
     p.add(pb2); 

     p.add(new JProgressBar(model)); 
     final ColorProgressBar pb4 = new ColorProgressBar(model); 
     p.add(pb4.layer); 

     JPanel box = new JPanel(); 
     box.add(new JButton(new AbstractAction("+10") { 
      private int i = 0; 
      @Override public void actionPerformed(ActionEvent e) { 
       model.setValue(i = (i>=100) ? 0 : i + 10); 
      } 
     })); 
     //http://msdn.microsoft.com/en-us/library/windows/desktop/aa511486.aspx 
     box.add(new JCheckBox(new AbstractAction(
       "<html>Turn the progress bar red<br />"+ 
         " when there is a user recoverable condition<br />"+ 
       " that prevents making further progress.") { 
      @Override public void actionPerformed(ActionEvent e) { 
       boolean b = ((JCheckBox)e.getSource()).isSelected(); 
       pb2.setForeground(b? new Color(255,0,0,100) : new Color(255,255,0,100)); 
       if (b) 
        pb4.setColor(Color.RED); 
       else 
        pb4.setColor(Color.YELLOW); 
       p.repaint(); 
      } 
     })); 

     JPanel panel = new JPanel(new BorderLayout()); 
     panel.add(p, BorderLayout.NORTH); 
     panel.add(box, BorderLayout.SOUTH); 
     return panel; 
    } 
    public static void main(String[] args) { 
     EventQueue.invokeLater(new Runnable() { 
      @Override public void run() { 
       createAndShowGUI(); 
      } 
     }); 
    } 
    public static void createAndShowGUI() { 
     try { 
      UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); 
     } catch(Exception e) { 
      e.printStackTrace(); 
     } 
     JFrame f = new JFrame(); 
     f.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); 
     f.getContentPane().add(new Test2().makeUI()); 
     f.setSize(320, 240); 
     f.setLocationRelativeTo(null); 
     f.setVisible(true); 
    } 
} 

class ColorProgressBar extends JProgressBar { 
    private static final long serialVersionUID = -1265489165072929352L; 

    private BlockedColorLayerUI colorUI = new BlockedColorLayerUI(); 
    public JLayer<JProgressBar> layer; 
    private PropertyChangeSupport supporter = new PropertyChangeSupport(new WeakReference<ColorProgressBar>(this)); 

    public ColorProgressBar(BoundedRangeModel model) { 
     super(model); 
     layer = new JLayer<JProgressBar>(this, colorUI); 
    } 

    public Color getColor() { 
     if (colorUI == null) 
      return null; 

     return colorUI.color; 
    } 

    public void setColor(Color color) { 
     Color oldColor = colorUI.color; 
     colorUI.color = color; 
     supporter.firePropertyChange("color", oldColor, color); 
    } 

//  @Override 
//  public void paintComponents(Graphics g) { 
//   layer.paintComponents(g); 
//  } 

    class BlockedColorLayerUI extends LayerUI<JProgressBar> { 
     public Color color = null; 
     private BufferedImage bi; 
     private int prevw = -1; 
     private int prevh = -1; 
     @Override public void paint(Graphics g, JComponent c) { 
      if(color != null) { 
       JLayer<?> jlayer = (JLayer<?>)c; 
       JProgressBar progress = (JProgressBar)jlayer.getView(); 
       int w = progress.getSize().width; 
       int h = progress.getSize().height; 

       if(bi==null || w!=prevw || h!=prevh) { 
        bi = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB); 
       } 
       prevw = w; 
       prevh = h; 

       Graphics2D g2 = bi.createGraphics(); 
       super.paint(g2, c); 
       g2.dispose(); 

       Image image = c.createImage(
         new FilteredImageSource(bi.getSource(), 
           new ColorFilter(color))); 
       g.drawImage(image, 0, 0, c); 
      } else { 
       super.paint(g, c); 
      } 
     } 
    } 
    class ColorFilter extends RGBImageFilter { 
     Color color; 

     public ColorFilter(Color color) { 
      this.color = color; 
     } 

     @Override public int filterRGB(int x, int y, int argb) { 
      int r = (int)((argb >> 16) & 0xff); 
      int g = (int)((argb >> 8) & 0xff); 
      int b = (int)((argb  ) & 0xff); 
      return (argb & color.getRGB()) | (g<<16) | (r<<8) | (b); 
     } 
    } 
} 
+0

是否有写入方法,不得不引用.layer字段?我觉得即使我记录了这种方法,但组织中的其他人可能会将其错误地挂钩,因为Swing或多或少地被设计成可以自己添加JComponents而不是其中的字段。 – Jesse

+0

有趣的SSCCE! –

相关问题