JProgressbar:如何根据进度改变颜色?

是否可以根据进度的值更改条形颜色? 我尝试了以下但它不起作用:

percentUsed = (int)(((float) used / (float) max) * BAR_PERCENTAGE); if (percentUsed >= ORANGE_THRESHOLD && 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(); 

我猜这不是一件微不足道的事情,因为JProgressbar并不意味着以这种方式使用……但是它有可能还是有其他选择?

在此处输入图像描述

 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 worker = new SwingWorker() { @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); } } } 

您可以这样做:

  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 

这里有一个主题。 设置JProgressBar文本的颜色

此链接也有一个示例演示。 如何更改颜色进度条

正如您所注意到的,不依赖于依赖于价值的“进步”绘画。 从理论上讲,动态设置progressBar实例的前提(取决于值)是要走的路。

但是:progressBar绘画的细节依赖于LAF

  • 在简单的LAF(如Metal)中设置前景很好
  • 在完全可换肤的LAF(如基于合成器的LAF)中支持每个实例的蒙皮(fi Nimbus)你可以尝试提供一个使用前景的Painter
  • 在不可换肤的LAF中没有办法(除了覆盖混凝土LAF并尝试挂钩绘画代码)

一些片段:

  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(); 

感谢您的帮助,但通过反复试验,我找到了一种方法,可以使用我现有的代码来改变颜色。

我不确定它是否是JPrgressbar的怪癖但是如果调用执行以下调用,前景栏颜色可以动态更改,只需最少的返工:

 progressBar.setStringPainted(true);