Google Tag Manager

Showing posts with label LinearGradientPaint. Show all posts
Showing posts with label LinearGradientPaint. Show all posts

2019/12/30

Create a speedometer by changing the shape of JProgressBar to a donut-shaped semicircle

Code

class SolidGaugeUI extends BasicProgressBarUI {
  private final int[] pallet;
  private final double extent;

  protected SolidGaugeUI(int range, double extent) {
    super();
    this.pallet = makeGradientPallet(range);
    this.extent = extent;
  }

  @Override public void paint(Graphics g, JComponent c) {
    Rectangle rect = SwingUtilities.calculateInnerArea(progressBar, null);
    if (rect.isEmpty()) {
      return;
    }
    Graphics2D g2 = (Graphics2D) g.create();
    g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
                        RenderingHints.VALUE_ANTIALIAS_ON);

    // double extent = -150d;
    double start = 90d + extent * .5;
    double degree = extent * progressBar.getPercentComplete();
    double or = Math.min(rect.width, rect.height);
    double cx = rect.getCenterX();
    double cy = rect.getMaxY();
    double sz = or * 2d;
    double ir = or * .6;
    Shape inner = new Arc2D.Double(
        cx - ir, cy - ir, ir * 2d, ir * 2d, start, -extent, Arc2D.PIE);
    Shape outer = new Arc2D.Double(
        cx - or, cy - or, sz, sz, start, -extent, Arc2D.PIE);
    Shape sector = new Arc2D.Double(
        cx - or, cy - or, sz, sz, start, -degree, Arc2D.PIE);

    Area foreground = new Area(sector);
    Area background = new Area(outer);
    Area hole = new Area(inner);

    foreground.subtract(hole);
    background.subtract(hole);

    // Draw the track
    g2.setPaint(new Color(0xDD_DD_DD));
    g2.fill(background);

    // Draw the circular sector
    g2.setPaint(getColorFromPallet(
        pallet, progressBar.getPercentComplete()));
    g2.fill(foreground);

    // Draw ...
    Font font = progressBar.getFont();
    float fsz = font.getSize2D();
    float min = (float) (cx - or - fsz);
    float max = (float) (cx + or + 4d);
    g2.setPaint(progressBar.getForeground());
    g2.drawString(
        Objects.toString(progressBar.getMinimum()), min, (float) cy);
    g2.drawString(Objects.toString(
        progressBar.getMaximum()), max, (float) cy);

    // Deal with possible text painting
    if (progressBar.isStringPainted()) {
      float h = (float) cy - fsz;
      String str = String.format("%d", progressBar.getValue());
      float vx = (float) cx - g2.getFontMetrics().stringWidth(str) * .5f;
      g2.drawString(str, vx, h);
      float ksz = fsz * .66f;
      g2.setFont(font.deriveFont(ksz));
      String kmh = "㎞/h";
      float tx = (float) cx - g2.getFontMetrics().stringWidth(kmh) * .5f;
      g2.drawString(kmh, tx, h + ksz);
    }
    g2.dispose();
  }

  private static int[] makeGradientPallet(int range) {
    BufferedImage image = new BufferedImage(
        range, 1, BufferedImage.TYPE_INT_RGB);
    Graphics2D g2 = image.createGraphics();
    Point2D start = new Point2D.Float();
    Point2D end = new Point2D.Float(range - 1f, 0f);
    float[] dist = {0f, .8f, .9f, 1f};
    Color[] colors = {Color.GREEN, Color.YELLOW, Color.ORANGE, Color.RED};
    g2.setPaint(new LinearGradientPaint(start, end, dist, colors));
    g2.fillRect(0, 0, range, 1);
    g2.dispose();

    int width = image.getWidth(null);
    int[] pallet = new int[width];
    PixelGrabber pg = new PixelGrabber(image, 0, 0, width, 1, pallet, 0, width);
    try {
      pg.grabPixels();
    } catch (InterruptedException ex) {
      ex.printStackTrace();
      Toolkit.getDefaultToolkit().beep();
      Thread.currentThread().interrupt();
    }
    return pallet;
  }

  private static Color getColorFromPallet(int[] pallet, double pos) {
    if (pos < 0d || pos > 1d) {
      throw new IllegalArgumentException("Parameter outside of expected range");
    }
    int i = (int) (pallet.length * pos);
    int max = pallet.length - 1;
    int index = Math.min(Math.max(i, 0), max);
    return new Color(pallet[index] & 0x00_FF_FF_FF);
  }
}

References

2015/05/29

Dynamically change the color of JProgressBar based on its value

Code

class GradientPalletProgressBarUI extends BasicProgressBarUI {
  private final int[] pallet;
  protected GradientPalletProgressBarUI() {
    super();
    this.pallet = makeGradientPallet();
  }

  private static int[] makeGradientPallet() {
    BufferedImage image = new BufferedImage(100, 1, BufferedImage.TYPE_INT_RGB);
    Graphics2D g2  = image.createGraphics();
    Point2D start  = new Point2D.Float();
    Point2D end    = new Point2D.Float(99, 0);
    float[] dist   = {0f, .5f, 1f};
    Color[] colors = {Color.RED, Color.YELLOW, Color.GREEN};
    g2.setPaint(new LinearGradientPaint(start, end, dist, colors));
    g2.fillRect(0, 0, 100, 1);
    g2.dispose();

    int width = image.getWidth(null);
    int[] pallet = new int[width];
    PixelGrabber pg = new PixelGrabber(image, 0, 0, width, 1, pallet, 0, width);
    try {
      pg.grabPixels();
    } catch (InterruptedException ex) {
      ex.printStackTrace();
    }
    return pallet;
  }

  private static Color getColorFromPallet(int[] pallet, float x) {
    if (x < 0f || x > 1f) {
      throw new IllegalArgumentException("Parameter outside of expected range");
    }
    int i = (int) (pallet.length * x);
    int max = pallet.length - 1;
    int index = Math.min(Math.max(i, 0), max);
    return new Color(pallet[index] & 0x00_FF_FF_FF);
    // translucent
    // int pix = pallet[index] & 0x00_FF_FF_FF | (0x64 << 24);
    // return new Color(pix), true);
  }

  @Override public void paintDeterminate(Graphics g, JComponent c) {
    Insets b = progressBar.getInsets(); // area for border
    int barRectWidth  = progressBar.getWidth()  - b.right - b.left;
    int barRectHeight = progressBar.getHeight() - b.top   - b.bottom;
    if (barRectWidth <= 0 || barRectHeight <= 0) {
      return;
    }
    // int cellLength = getCellLength();
    // int cellSpacing = getCellSpacing();
    // amount of progress to draw
    int amountFull = getAmountFull(b, barRectWidth, barRectHeight);

    // draw the cells
    if (progressBar.getOrientation() == SwingConstants.HORIZONTAL) {
      float x = amountFull / (float) barRectWidth;
      g.setColor(getColorFromPallet(pallet, x));
      g.fillRect(b.left, b.top, amountFull, barRectHeight);
    } else { // VERTICAL
      float y = amountFull / (float) barRectHeight;
      g.setColor(getColorFromPallet(pallet, y));
      g.fillRect(b.left, barRectHeight + b.bottom - amountFull, barRectWidth, amountFull);
    }
    // Deal with possible text painting
    if (progressBar.isStringPainted()) {
      paintString(g, b.left, b.top, barRectWidth, barRectHeight, amountFull, b);
    }
  }
}

References

2012/09/24

create a gradient titled separator

Code

class TitledSeparator extends JLabel {
  private final String title;
  private final Color target;
  private final int height;
  private final int titlePosition;

  public TitledSeparator(String title, int height, int titlePosition) {
    this(title, null, height, titlePosition);
  }

  public TitledSeparator(
      String title, Color target, int height, int titlePosition) {
    super();
    this.title = title;
    this.target = target;
    this.height = height;
    this.titlePosition = titlePosition;
    updateBorder();
  }

  private void updateBorder() {
    Icon icon = new TitledSeparatorIcon();
    setBorder(BorderFactory.createTitledBorder(
        BorderFactory.createMatteBorder(height, 0, 0, 0, icon), title,
        TitledBorder.DEFAULT_JUSTIFICATION, titlePosition));
  }

  @Override public Dimension getMaximumSize() {
    Dimension d = super.getPreferredSize();
    d.width = Short.MAX_VALUE;
    return d;
  }

  @Override public void updateUI() {
    super.updateUI();
    EventQueue.invokeLater(this::updateBorder);
  }

  private class TitledSeparatorIcon implements Icon {
    private int width = -1;
    private Paint painter1;
    private Paint painter2;

    @Override public void paintIcon(Component c, Graphics g, int x, int y) {
      int w = c.getWidth();
      if (w != width || painter1 == null || painter2 == null) {
        width = w;
        Point2D start = new Point2D.Float();
        Point2D end = new Point2D.Float(width, 0);
        float[] dist = {0f, 1f};
        Color ec = Optional.ofNullable(getBackground())
            .orElse(UIManager.getColor("Panel.background"));
        Color sc = Optional.ofNullable(target).orElse(ec);
        painter1 = new LinearGradientPaint(
            start, end, dist, new Color[] {sc.darker(), ec});
        painter2 = new LinearGradientPaint(
            start, end, dist, new Color[] {sc.brighter(), ec});
      }
      int h = getIconHeight() / 2;
      Graphics2D g2  = (Graphics2D) g.create();
      g2.setPaint(painter1);
      g2.fillRect(x, y, width, getIconHeight());
      g2.setPaint(painter2);
      g2.fillRect(x, y + h, width, getIconHeight() - h);
      g2.dispose();
    }

    @Override public int getIconWidth() {
      return 200; // sample width
    }

    @Override public int getIconHeight() {
      return height;
    }
  }
}

References

2011/06/27

Gradient translucent track JSlider

Code

UIManager.put("Slider.horizontalThumbIcon", new Icon() {
  @Override public void paintIcon(Component c, Graphics g, int x, int y) {}
  @Override public int getIconWidth()  { return 15; }
  @Override public int getIconHeight() { return 64; }
});
UIManager.put("Slider.trackWidth", 64);
UIManager.put("Slider.majorTickLength", 6);

JSlider slider = makeSlider();
slider.setUI(new MetalSliderUI() {
  int[] pallet = makeGradientPallet();
  @Override public void paintTrack(Graphics g) {
    // Color trackColor = !slider.isEnabled()
    //   ? MetalLookAndFeel.getControlShadow() : slider.getForeground();
    boolean leftToRight = true; //MetalUtils.isLeftToRight(slider);
    Color controlDarkShadow = Color.GRAY;
    Color controlHighlight = new Color(200, 255, 200);
    Color controlShadow = new Color(0, 100, 0);

    g.translate(trackRect.x, trackRect.y);

    int trackLeft = 0;
    int trackTop = 0;
    int trackRight = 0;
    int trackBottom = 0;

    // Draw the track
    if (slider.getOrientation() == SwingConstants.HORIZONTAL) {
      trackBottom = (trackRect.height - 1) - getThumbOverhang();
      trackTop = trackBottom - (getTrackWidth() - 1);
      trackRight = trackRect.width - 1;
    } else {
      if (leftToRight) {
        trackLeft = (trackRect.width - getThumbOverhang()) - getTrackWidth();
        trackRight = (trackRect.width - getThumbOverhang()) - 1;
      } else {
        trackLeft = getThumbOverhang();
        trackRight = getThumbOverhang() + getTrackWidth() - 1;
      }
      trackBottom = trackRect.height - 1;
    }

    if (slider.isEnabled()) {
      g.setColor(controlDarkShadow);
      g.drawRect(trackLeft, trackTop,
                (trackRight - trackLeft) - 1, (trackBottom - trackTop) - 1);

      g.setColor(controlHighlight);
      g.drawLine(trackLeft + 1, trackBottom, trackRight, trackBottom);
      g.drawLine(trackRight, trackTop + 1, trackRight, trackBottom);

      g.setColor(controlShadow);
      g.drawLine(trackLeft + 1, trackTop + 1, trackRight - 2, trackTop + 1);
      g.drawLine(trackLeft + 1, trackTop + 1, trackLeft + 1, trackBottom - 2);
    } else {
      g.setColor(controlShadow);
      g.drawRect(trackLeft, trackTop,
                 (trackRight - trackLeft) - 1, (trackBottom - trackTop) - 1);
    }

    // Draw the fill
    int middleOfThumb = 0;
    int fillTop = 0;
    int fillLeft = 0;
    int fillBottom = 0;
    int fillRight = 0;

    if (slider.getOrientation() == SwingConstants.HORIZONTAL) {
      middleOfThumb = thumbRect.x + (thumbRect.width / 2);
      middleOfThumb -= trackRect.x; // To compensate for the g.translate()
      fillTop = !slider.isEnabled() ? trackTop : trackTop + 1;
      fillBottom = !slider.isEnabled() ? trackBottom - 1 : trackBottom - 2;

      if (!drawInverted()) {
        fillLeft = !slider.isEnabled() ? trackLeft : trackLeft + 1;
        fillRight = middleOfThumb;
      } else {
        fillLeft = middleOfThumb;
        fillRight = !slider.isEnabled() ? trackRight - 1 : trackRight - 2;
      }
    } else {
      middleOfThumb = thumbRect.y + (thumbRect.height / 2);
      middleOfThumb -= trackRect.y; // To compensate for the g.translate()
      fillLeft = !slider.isEnabled() ? trackLeft : trackLeft + 1;
      fillRight = !slider.isEnabled() ? trackRight - 1 : trackRight - 2;

      if (!drawInverted()) {
        fillTop = middleOfThumb;
        fillBottom = !slider.isEnabled() ? trackBottom - 1 : trackBottom - 2;
      } else {
        fillTop = !slider.isEnabled() ? trackTop : trackTop + 1;
        fillBottom = middleOfThumb;
      }
    }

    if (slider.isEnabled()) {
      g.setColor(slider.getBackground());
      g.drawLine(fillLeft, fillTop, fillRight, fillTop );
      g.drawLine(fillLeft, fillTop, fillLeft, fillBottom );

      double x = (fillRight - fillLeft) / (double) (trackRight - trackLeft);
      g.setColor(getColorFromPallet(pallet, x));
      g.fillRect(fillLeft + 1, fillTop + 1,
                 fillRight - fillLeft, fillBottom - fillTop);
    } else {
      g.setColor(controlShadow);
      g.fillRect(fillLeft, fillTop, fillRight - fillLeft, trackBottom - trackTop);
    }

    int yy = trackTop + (trackBottom - trackTop) / 2;
    for (int i = 10; i >= 0; i--) {
      g.setColor(new Color(1f, 1f, 1f, i * .07f));
      g.drawLine(trackLeft + 2, yy, (trackRight - trackLeft), yy);
      yy--;
    }
    g.translate(-trackRect.x, -trackRect.y);
  }
});

// ...
private static int[] makeGradientPallet() {
  BufferedImage image = new BufferedImage(100, 1, BufferedImage.TYPE_INT_RGB);
  Graphics2D g2  = image.createGraphics();
  Point2D start  = new Point2D.Float(0f, 0f);
  Point2D end    = new Point2D.Float(99f, 0f);
  float[] dist   = {0f, .5f, 1f};
  Color[] colors = {Color.RED, Color.YELLOW, Color.GREEN};
  g2.setPaint(new LinearGradientPaint(start, end, dist, colors));
  g2.fillRect(0, 0, 100, 1);
  int width  = image.getWidth(null);
  int[] pallet = new int[width];
  PixelGrabber pg = new PixelGrabber(image, 0, 0, width, 1, pallet, 0, width);
  try {
    pg.grabPixels();
  } catch (Exception e) {
    e.printStackTrace();
  }
  return pallet;
}

private static Color getColorFromPallet(int[] pallet, float x) {
  int i = (int) (pallet.length * x);
  int max = pallet.length-1;
  int index = i < 0 ? 0 : i > max ? max : i;
  int pix = pallet[index] & 0x00_FF_FF_FF | (0x64 << 24);
  return new Color(pix, true);
}

References