如何使JProgressBar与Windows LaF相匹配?

10

我一直在使用WindowsLookAndFeelJProgressBar一起工作,但我发现与本机进度条存在一些主要差异:


这是本机进度条的常规状态:

输入图像描述

而这是Java的:

输入图像描述

敏锐的眼睛可能会看到Java的顶部白色比本机更亮,绿色也稍微亮一点。此外,本机是“填充”的,而Java则有一个空边框。


现在,是本机不定的:

输入图像描述

和Java的:

输入图像描述

闪烁时间更短,速度更快(未显示)。此外,本机看起来像一个发光体,而Java则更像一个彗星(带尾巴,只从一侧...)。


最后一个问题,阻止的进度条:

输入图像描述

在Java中能做到这一点吗?


这里已经解决了几次带有红色颜色的阻塞栏问题,包括在JProgressBar中使用彩虹颜色。请问目标是什么?只是为了创建类似于Win7的颜色方案,注意大多数用户更改Win主题中的颜色(包括我自己==橙色),关于创建不确定性,不知道是否存在问题,在@trashgod的帖子中搜索。 - mKorbel
关于JProgressBar的最佳文章在@aterai的帖子中,必须使用GradientPaint而不是纯色。 - mKorbel
1个回答

5
  • 这只是一个关于最终问题的例子:
    • Windows 7(绿色进度条)
    • JDK 1.7.0_25(WindowsLookAndFeel)

TurnProgressBarRedTest

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

public class TurnProgressBarRedTest {
  public JComponent makeUI() {
    final BoundedRangeModel model = new DefaultBoundedRangeModel();
    final BlockedColorLayerUI layerUI = new BlockedColorLayerUI();
    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));
    p.add(new JLayer<JProgressBar>(new JProgressBar(model), layerUI));

    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) : pb1.getForeground());
        layerUI.isPreventing = b;
        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 TurnProgressBarRedTest().makeUI());
    f.setSize(320, 240);
    f.setLocationRelativeTo(null);
    f.setVisible(true);
  }
}
class BlockedColorLayerUI extends LayerUI<JProgressBar> {
  public boolean isPreventing = false;
  private BufferedImage bi;
  private int prevw = -1;
  private int prevh = -1;
  @Override public void paint(Graphics g, JComponent c) {
    if(isPreventing) {
      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 RedGreenChannelSwapFilter()));
      g.drawImage(image, 0, 0, null);
    } else {
      super.paint(g, c);
    }
  }
}
class RedGreenChannelSwapFilter extends RGBImageFilter {
  @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 & 0xff000000) | (g<<16) | (r<<8) | (b);
  }
}

1
这是在Windows 8.1中的样子:http://i.imgur.com/nUYsSkB.png 不幸的是,它并不工作得很好。 - randers

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接