JProgressbar: comment changer de couleur en fonction des progrès?


Est-il possible de changer la couleur de la barre en fonction de la valeur de la progression? J'ai essayé ce qui suit mais cela ne fonctionne pas:

percentUsed = (int)(((float) used / (float) max) * BAR_PERCENTAGE);
      if (percentUsed >= ORANGE_THRESHOLD &&  percentUsed < RED_THRESHOLD) {
        if (!m_orangeIndicator) {
          LOG.warn(String.format("Memory usage exceeds %d percent.", ORANGE_THRESHOLD));
          m_orangeIndicator = true;
        }
        colour = Color.ORANGE;
        m_redIndicator = false;
      }
      else if (percentUsed >= RED_THRESHOLD) {
        if (!m_redIndicator) {
          LOG.warn(String.format("Memory usage exceeds %d percent.", RED_THRESHOLD));
          m_orangeIndicator = true;
          m_redIndicator = true;
        }
        colour = Color.RED;
      }
      else {
        m_orangeIndicator = false;
        m_redIndicator = false;
        colour = Color.GREEN;
      }
      m_memUsageBar.setForeground(colour);
      m_memUsageBar.setValue(percentUsed);
      m_memUsageBar.updateUI();

Je suppose que ce n'est pas une chose triviale à faire car JProgressbar n'est pas destiné à être utilisé de cette façon... Mais est-ce possible ou existe-t-il des alternatives?

Author: mKorbel, 2012-09-21

4 answers

entrez la description de l'image ici

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

public class GradientPalletProgressBarDemo {
  public JComponent makeUI() {
    final JProgressBar progressBar = new JProgressBar();
    progressBar.setOpaque(false);
    progressBar.setUI(new GradientPalletProgressBarUI());

    JPanel p = new JPanel();
    p.add(progressBar);
    p.add(new JButton(new AbstractAction("Start") {
      @Override public void actionPerformed(ActionEvent e) {
        SwingWorker<Void,Void> worker = new SwingWorker<Void,Void>() {
          @Override public Void doInBackground() {
            int current = 0, lengthOfTask = 100;
            while(current<=lengthOfTask && !isCancelled()) {
              try { // dummy task
                Thread.sleep(50);
              } catch(InterruptedException ie) {
                return null;
              }
              setProgress(100 * current / lengthOfTask);
              current++;
            }
            return null;
          }
        };
        worker.addPropertyChangeListener(new ProgressListener(progressBar));
        worker.execute();
      }
    }));
    return p;
  }
  public static void main(String[] args) {
    EventQueue.invokeLater(new Runnable() {
      @Override public void run() {
        createAndShowGUI();
      }
    });
  }
  public static void createAndShowGUI() {
    JFrame frame = new JFrame();
    frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
    frame.getContentPane().add(new GradientPalletProgressBarDemo().makeUI());
    frame.setSize(320, 240);
    frame.setLocationRelativeTo(null);
    frame.setVisible(true);
  }
}
class ProgressListener implements PropertyChangeListener {
  private final JProgressBar progressBar;
  ProgressListener(JProgressBar progressBar) {
    this.progressBar = progressBar;
    this.progressBar.setValue(0);
  }
  @Override public void propertyChange(PropertyChangeEvent evt) {
    String strPropertyName = evt.getPropertyName();
    if("progress".equals(strPropertyName)) {
      progressBar.setIndeterminate(false);
      int progress = (Integer)evt.getNewValue();
      progressBar.setValue(progress);
    }
  }
}
class GradientPalletProgressBarUI extends BasicProgressBarUI {
  private final int[] pallet;
  public 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(0f, 0f);
    Point2D end    = new Point2D.Float(99f, 0f);
    float[] dist   = {0.0f, 0.5f, 1.0f};
    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(Exception e) {
      e.printStackTrace();
    }
    return pallet;
  }
  private static Color getColorFromPallet(int[] pallet, float x) {
    if(x < 0.0 || x > 1.0) {
      throw new IllegalArgumentException("Parameter outside of expected range");
    }
    int i = (int)(pallet.length * x);
    int max = pallet.length-1;
    int index = i<0?0:i>max?max:i;
    int pix = pallet[index] & 0x00ffffff | (0x64 << 24);
    return new Color(pix, true);
  }
  @Override public void paintDeterminate(Graphics g, JComponent c) {
    if (!(g instanceof Graphics2D)) {
      return;
    }
    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);

    if(progressBar.getOrientation() == JProgressBar.HORIZONTAL) {
      // draw the cells
      float x = amountFull / (float)barRectWidth;
      g.setColor(getColorFromPallet(pallet, x));
      g.fillRect(b.left, b.top, amountFull, barRectHeight);

    } else { // VERTICAL
      //...
    }
    // Deal with possible text painting
    if(progressBar.isStringPainted()) {
      paintString(g, b.left, b.top, barRectWidth, barRectHeight, amountFull, b);
    }
  }
}
 6
Author: aterai, 2012-10-16 16:25:36

Vous pouvez faire l'une ou l'autre de cette façon:

           UIManager.put("ProgressBar.background", Color.BLACK); //colour of the background    

UIManager.put("ProgressBar.foreground", Color.RED);  //colour of progress bar
    UIManager.put("ProgressBar.selectionBackground",Color.YELLOW);  //colour of percentage counter on black background    
UIManager.put("ProgressBar.selectionForeground",Color.BLUE);  //colour of precentage counter on red background

Il y a un fil ici. Définir les couleurs d'un texte JProgressBar

Il y a aussi un exemple de démo ici sur ce lien. comment changer la barre de progression des couleurs

 4
Author: UVM, 2017-05-23 11:43:51

Comme vous l'avez remarqué, la peinture "progression" dépendante de la valeur n'est-elle pas prise en charge. Théoriquement, définir dynamiquement le foregound de l'instance progressBar (c'est-à-dire en fonction de la valeur) est la voie à suivre.

Mais: les détails de la peinture progressBar sont fortement LAF dépendant

  • dans les LAFs simples (comme le métal), le réglage du premier plan est correct
  • dans les LAFS entièrement skinnables (comme LAF basé sur un synthé) qui prennent en charge le skinning par instance (f. i. Nimbus), vous pouvez essayer de fournir un Peintre qui utilise le premier plan
  • dans les LAFs non skinnables, il n'y a aucun moyen (sauf remplacer le LAF concret et essayer de se connecter au code de peinture)

Un extrait:

    final JProgressBar bar = new JProgressBar();
    // used for Nimbus (beware: just a proof-of-concept - this looks extremely ugly!)
    Painter p = new Painter() {

        @Override
        public void paint(Graphics2D g, Object object, int width, int height) {
            JProgressBar bar = (JProgressBar) object;
            g.setColor(bar.getForeground());
            g.fillRect(0, 0, width, height);
        }

    };
    // install custom painter on the bar
    UIDefaults properties = new UIDefaults();
    properties.put("ProgressBar[Enabled].foregroundPainter", p);
    bar.putClientProperty("Nimbus.Overrides", properties);

    // simulate progress
    Action action = new AbstractAction("timer") {

        @Override
        public void actionPerformed(ActionEvent e) {
            bar.setValue(bar.getValue() + 1);
            // change foreground value-dependent
            if (bar.getValue() > 10) {
                bar.setForeground(Color.RED);
            }
        }
    };
    Timer timer = new Timer(100, action);
    timer.start();
 1
Author: kleopatra, 2012-09-21 11:16:10

Merci pour l'aide, mais par essais et erreurs, j'ai trouvé un moyen de changer la couleur en utilisant mon code existant.

Je ne sais pas si c'est la bizarrerie de JPrgressbar mais si l'appel fait l'appel suivant, la couleur de la barre de premier plan peut être modifiée dynamiquement avec un minimum de retouche:

progressBar.setStringPainted(true);
 1
Author: Foo, 2012-09-24 23:28:53