如何使用Netbeans的不确定进度条样式?

时间:2014-06-25 13:20:16

标签: java swing netbeans jprogressbar nimbus

我使用Nimbus look& amp;编程Java应用程序感觉。不幸的是,Nimbus的不确定JProgressBars外观和外观。感觉是 AWFUL (见下文):

enter image description here

另一方面,我注意到Netbeans的Nimbus外观&感觉有一个不同的不确定的JProgressBar风格,看起来好多了(见下文):

enter image description here

如何在我自己的应用程序中使用此样式?

2 个答案:

答案 0 :(得分:3)

您可以自己编写Painter<JComponent>

import java.awt.*;
import java.awt.event.*;
import java.awt.geom.*;
import java.beans.*;
import javax.swing.*;
import javax.swing.plaf.nimbus.*;

public final class IndeterminateStyleTest {
  private final BoundedRangeModel model = new DefaultBoundedRangeModel();
  public JComponent makeUI() {
    JProgressBar progressBar0 = new JProgressBar(model);

    UIDefaults d = new UIDefaults();
    d.put("ProgressBar[Enabled+Indeterminate].foregroundPainter", new IndeterminateRegionPainter());

    JProgressBar progressBar1 = new JProgressBar(model);
    progressBar1.putClientProperty("Nimbus.Overrides", d);

    progressBar0.setIndeterminate(true);
    progressBar1.setIndeterminate(true);

    JPanel p = new JPanel();
    p.setBorder(BorderFactory.createEmptyBorder(32, 5, 32, 5));
    p.add(progressBar0);
    p.add(progressBar1);
    return p;
  }
  public static void main(String[] args) {
    EventQueue.invokeLater(new Runnable() {
      @Override public void run() {
        createAndShowGUI();
      }
    });
  }
  public static void createAndShowGUI() {
    try {
      for (UIManager.LookAndFeelInfo laf : UIManager.getInstalledLookAndFeels()) {
        if ("Nimbus".equals(laf.getName())) {
          UIManager.setLookAndFeel(laf.getClassName());
        }
      }
    } catch (ClassNotFoundException | InstantiationException |
               IllegalAccessException | UnsupportedLookAndFeelException ex) {
      ex.printStackTrace();
    }
    JFrame f = new JFrame();
    f.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
    f.getContentPane().add(new IndeterminateStyleTest().makeUI());
    f.setSize(320, 240);
    f.setLocationRelativeTo(null);
    f.setVisible(true);
  }
}

class IndeterminateRegionPainter extends AbstractRegionPainter {
  // Copied from javax.swing.plaf.nimbus.ProgressBarPainter.java
  private Color color17 = decodeColor("nimbusOrange",  .0f,           .0f,         .0f,       -156);
  private Color color18 = decodeColor("nimbusOrange", -.015796512f,   .02094239f, -.15294117f,   0);
  private Color color19 = decodeColor("nimbusOrange", -.004321605f,   .02094239f, -.0745098f,    0);
  private Color color20 = decodeColor("nimbusOrange", -.008021399f,   .02094239f, -.10196078f,   0);
  private Color color21 = decodeColor("nimbusOrange", -.011706904f,  -.1790576f,  -.02352941f,   0);
  private Color color22 = decodeColor("nimbusOrange", -.048691254f,   .02094239f, -.3019608f,    0);
  private Color color23 = decodeColor("nimbusOrange",  .003940329f,  -.7375322f,   .17647058f,   0);
  private Color color24 = decodeColor("nimbusOrange",  .005506739f,  -.46764207f,  .109803915f,  0);
  private Color color25 = decodeColor("nimbusOrange",  .0042127445f, -.18595415f,  .04705882f,   0);
  private Color color26 = decodeColor("nimbusOrange",  .0047626942f,  .02094239f,  .0039215684f, 0);
  private Color color27 = decodeColor("nimbusOrange",  .0047626942f, -.15147138f,  .1607843f,    0);
  private Color color28 = decodeColor("nimbusOrange",  .010665476f,  -.27317524f,  .25098038f,   0);
  private Rectangle2D rect = new Rectangle2D.Float(0, 0, 0, 0);
  private Path2D path = new Path2D.Float();
  private PaintContext ctx = new PaintContext(new Insets(5, 5, 5, 5), new Dimension(29, 19), false);
  @Override public void doPaint(Graphics2D g, JComponent c, int width, int height, Object[] extendedCacheKeys) {
    path = decodePath1();
    g.setPaint(color17);
    g.fill(path);
    rect = decodeRect3();
    g.setPaint(decodeGradient5(rect));
    g.fill(rect);
    rect = decodeRect4();
    g.setPaint(decodeGradient6(rect));
    g.fill(rect);
  }
  @Override public PaintContext getPaintContext() {
    return ctx;
  }
  private Path2D decodePath1() {
    path.reset();
    path.moveTo(decodeX(0.6f), decodeY(0.12666667f));
    path.curveTo(decodeAnchorX(0.6000000238418579f, -2.0f), decodeAnchorY(0.12666666507720947f, 0.0f), decodeAnchorX(0.12666666507720947f, 0.0f), decodeAnchorY(0.6000000238418579f, -2.0f), decodeX(0.12666667f), decodeY(0.6f));
    path.curveTo(decodeAnchorX(0.12666666507720947f, 0.0f), decodeAnchorY(0.6000000238418579f, 2.0f), decodeAnchorX(0.12666666507720947f, 0.0f), decodeAnchorY(2.4000000953674316f, -2.0f), decodeX(0.12666667f), decodeY(2.4f));
    path.curveTo(decodeAnchorX(0.12666666507720947f, 0.0f), decodeAnchorY(2.4000000953674316f, 2.0f), decodeAnchorX(0.6000000238418579f, -2.0f), decodeAnchorY(2.8933334350585938f, 0.0f), decodeX(0.6f), decodeY(2.8933334f));
    path.curveTo(decodeAnchorX(0.6000000238418579f, 2.0f), decodeAnchorY(2.8933334350585938f, 0.0f), decodeAnchorX(3.0f, 0.0f), decodeAnchorY(2.8933334350585938f, 0.0f), decodeX(3.0f), decodeY(2.8933334f));
    path.lineTo(decodeX(3.0f), decodeY(2.6f));
    path.lineTo(decodeX(0.4f), decodeY(2.6f));
    path.lineTo(decodeX(0.4f), decodeY(0.4f));
    path.lineTo(decodeX(3.0f), decodeY(0.4f));
    path.lineTo(decodeX(3.0f), decodeY(0.120000005f));
    path.curveTo(decodeAnchorX(3.0f, 0.0f), decodeAnchorY(0.12000000476837158f, 0.0f), decodeAnchorX(0.6000000238418579f, 2.0f), decodeAnchorY(0.12666666507720947f, 0.0f), decodeX(0.6f), decodeY(0.12666667f));
    path.closePath();
    return path;
  }
  private Rectangle2D decodeRect3() {
    rect.setRect(decodeX(0.4f), //x
                 decodeY(0.4f), //y
                 decodeX(3.0f) - decodeX(0.4f), //width
                 decodeY(2.6f) - decodeY(0.4f)); //height
    return rect;
  }
  private Rectangle2D decodeRect4() {
    rect.setRect(decodeX(0.6f), //x
                 decodeY(0.6f), //y
                 decodeX(2.8f) - decodeX(0.6f), //width
                 decodeY(2.4f) - decodeY(0.6f)); //height
    return rect;
  }
  private Paint decodeGradient5(Shape s) {
    Rectangle2D bounds = s.getBounds2D();
    float x = (float)bounds.getX();
    float y = (float)bounds.getY();
    float w = (float)bounds.getWidth();
    float h = (float)bounds.getHeight();
    return decodeGradient((0.5f * w) + x, (0.0f * h) + y, (0.5f * w) + x, (1.0f * h) + y,
                          new float[] { 0.038709678f, 0.05483871f, 0.07096774f, 0.28064516f, 0.4903226f, 0.6967742f, 0.9032258f, 0.9241935f, 0.9451613f },
                          new Color[] { color18,
                                        decodeColor(color18, color19, 0.5f),
                                        color19,
                                        decodeColor(color19, color20, 0.5f),
                                        color20,
                                        decodeColor(color20, color21, 0.5f),
                                        color21,
                                        decodeColor(color21, color22, 0.5f),
                                        color22
                                      });
  }

  private Paint decodeGradient6(Shape s) {
    Rectangle2D bounds = s.getBounds2D();
    float x = (float)bounds.getX();
    float y = (float)bounds.getY();
    float w = (float)bounds.getWidth();
    float h = (float)bounds.getHeight();
    return decodeGradient((0.5f * w) + x, (0.0f * h) + y, (0.5f * w) + x, (1.0f * h) + y,
                          new float[] { 0.038709678f, 0.061290324f, 0.08387097f, 0.27258065f, 0.46129033f, 0.4903226f, 0.5193548f, 0.71774197f, 0.91612905f, 0.92419356f, 0.93225807f },
                          new Color[] { color23,
                                        decodeColor(color23, color24, 0.5f),
                                        color24,
                                        decodeColor(color24, color25, 0.5f),
                                        color25,
                                        decodeColor(color25, color26, 0.5f),
                                        color26,
                                        decodeColor(color26, color27, 0.5f),
                                        color27,
                                        decodeColor(color27, color28, 0.5f),
                                        color28
                                      });
  }
}

答案 1 :(得分:0)

您也可以从 JProgressBar 继承子类并覆盖 PaintComponent 方法。这使您可以完全自由地绘制任何您喜欢的东西。甚至可能比公认的解决方案更少的代码。

这是一个仅覆盖 Nimbus 不确定行为的示例,该示例具有更多类似窗口的渐变外观: Windows-like gradient look for Nimbus JProgressBar indeterminate

这个解决方案的缺点是你需要显式地 dispose() 组件(或者我可能还没有找到自动关闭执行器的合适方法)

import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.GradientPaint;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicReference;

import javax.swing.BorderFactory;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JProgressBar;
import javax.swing.UIManager;
import javax.swing.WindowConstants;

public final class Test
{
  public JComponent makeUI()
  {
    final JProgressBar progressBar=new GradientProgressBar();
    progressBar.setPreferredSize(new Dimension(700, 30));
    progressBar.setIndeterminate(true);
    progressBar.setStringPainted(true);
    progressBar.setString("Loading...");
    final JPanel p=new JPanel();
    p.setBorder(BorderFactory.createEmptyBorder(32, 5, 32, 5));
    p.add(progressBar);
    return p;
  }

  public static void main(String[] args)
  {
    EventQueue.invokeLater(()->createAndShowGUI());
  }

  public static void createAndShowGUI()
  {
    try
    {
      for (UIManager.LookAndFeelInfo laf:UIManager.getInstalledLookAndFeels())
      {
        if ("Nimbus".equals(laf.getName()))
        {
          UIManager.setLookAndFeel(laf.getClassName());
        }
      }
    }
    catch (Exception ex)
    {
      ex.printStackTrace();
    }
    JFrame f=new JFrame();
    f.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
    f.getContentPane().add(new Test().makeUI());
    f.setSize(800, 600);
    f.setLocationRelativeTo(null);
    f.setVisible(true);
  }
}

class GradientProgressBar extends JProgressBar
{
  private static final long serialVersionUID=8886375125424236114L;
  private static final int UPDATE_INTERVAL_MS=50;
  private static final AtomicInteger THREAD_NUM=new AtomicInteger();
  private static final AtomicReference<ScheduledThreadPoolExecutor> executor=new AtomicReference<>();
  private static final Font FONT=new Font("SansSerif", Font.BOLD, 12);
  private static final int R_BACK=214;
  private static final int G_BACK=217;
  private static final int B_BACK=223;
  private static final int COLOR_DELTA=20;
  private static final Color COLOR_BAR=new Color(191, 98, 4);

  private final AtomicInteger position=new AtomicInteger(-20);

  @Override
  protected void paintComponent(final Graphics g)
  {
    if (isIndeterminate())
    {
      drawGradient((Graphics2D) g);
      adjustPosition();
    }
    else
    {
      super.paintComponent(g);
    }
  }

  private void drawGradient(final Graphics2D g)
  {
    if (getWidth() > 0 && getHeight() > 0)
    {
      final int gradWidth=getWidth() / 4;
      final float posF=(float) position.get();
      for (int y=0;y < getWidth();y++)
      {
        GradientPaint grad=new GradientPaint(posF, 0.0f, getBackgroundAtY(y), posF + (float) gradWidth / 2.0f, 0.0f, COLOR_BAR);
        Rectangle rect=new Rectangle(0, y, position.get() + gradWidth / 2, 1);
        g.setPaint(grad);
        g.fill(rect);
        grad=new GradientPaint(posF + (float) gradWidth / 2.0f, 0.0f, COLOR_BAR, posF + (float) gradWidth, 0.0f, getBackgroundAtY(y));
        rect=new Rectangle(position.get() + gradWidth / 2, y, getWidth() - position.get(), 1);
        g.setPaint(grad);
        g.fill(rect);
      }
      drawTitle(g);
    }
  }

  public void drawTitle(final Graphics g)
  {
    if (isStringPainted() && getString() != null && !getString().isBlank())
    {
      g.setColor(Color.BLACK);
      final FontMetrics metrics=g.getFontMetrics(FONT);
      final int x=(getWidth() - metrics.stringWidth(getString())) / 2;
      final int y=(getHeight() - metrics.getHeight()) / 2 + metrics.getAscent();
      g.setFont(FONT);
      g.drawString(getString(), x, y);
    }
  }

  private Color getBackgroundAtY(final int y)
  {
    if (y <= 2 || y >= getHeight() - 2)
    {
      // Border
      return new Color(R_BACK - COLOR_DELTA, G_BACK - COLOR_DELTA, B_BACK - COLOR_DELTA);
    }
    // Vertical gradient
    final int height=(getHeight() - 4) / 2;
    final int delta=Math.abs(height - y);
    final int colorDelta=COLOR_DELTA * delta / height;
    return new Color(R_BACK + colorDelta, G_BACK + colorDelta, B_BACK + colorDelta);
  }

  @Override
  public void setIndeterminate(boolean newValue)
  {
    if (newValue != isIndeterminate())
    {
      super.setIndeterminate(newValue);
      if (newValue)
      {
        executor.set(new ScheduledThreadPoolExecutor(1, r -> new Thread(r, "guihelper_progress-" + THREAD_NUM.incrementAndGet())));
        executor.get().scheduleAtFixedRate(() -> repaint(), 0, UPDATE_INTERVAL_MS, TimeUnit.MILLISECONDS);
      }
      else
      {
        if (executor.get() != null)
        {
          executor.get().shutdownNow();
        }
      }
    }
  }

  public void dispose()
  {
    if (executor.get() != null)
    {
      executor.get().shutdownNow();
    }
  }

  private void adjustPosition()
  {
    int step=getWidth() * UPDATE_INTERVAL_MS / 10000;
    if (step <= 0)
    {
      step=1;
    }
    position.set(position.get() + step);
    if (position.get() > getWidth())
    {
      position.set(-getWidth() / 4);
    }
  }
}