2014-01-21 114 views
1

我試圖做一個health bar,並且可能是什麼原,它會開始了綠色,健康失去之後你會發現它會變成黃色,然後是橙色,然後紅色..什麼相對於此。的Java:平滑的色彩過渡

我試圖使用在此鏈路提供的方法:https://stackoverflow.com/questions/19841477/java-smooth-color-transition

從該鏈接的結果是此代碼,就從值100的測試爲0,但它在IllegalArgumentException在正常RedGreen結束,我的理由猜測是被高估255

Color to = Color.red; 
Color base = Color.green; 
int red = (int)Math.abs((100 * to.getRed()) + ((1 - 100) * base.getRed())); 
int green = (int)Math.abs((100 * to.getGreen()) + ((1 - 100) * base.getGreen())); 
int blue = (int)Math.abs((100 * to.getBlue()) + ((1 - 100) * base.getBlue())); 
setForeground(new Color(red, green, blue)); 

它並沒有真正的工作的價值,我絕對不知道我怎樣才能得到它transition我希望它的方式。

所以我HealthBar類中,我有一個update()方法

public void update() { 
    if (getValue() < 10) setForeground(Color.red); 
    else if (getValue() < 25) setForeground(Color.orange); 
    else if (getValue() < 60) setForeground(Color.yellow); 
    else setForeground(Color.green); 
} 

此代碼在某一點基本的轉變。

我需要創建領域在health bar的某些values使用某些colors,所以現在我有這個..

if (getValue() < 10) { 
    Color to = Color.black; 
    // Color current = getForeground() ? 
    Color from = Color.red; 
    // ? 
} 

我只想用一個例子的最後一位。

所以我知道我將會有一個color,我要和color這是一個基礎。我不太確定是否需要color。我現在看到的問題是轉換的步驟,因爲每個轉換都有不同的步驟。

摘要和問題
我不知道該如何實現什麼,我嘗試,我只知道可以肯定的是,我需要一個以和底座color,我提供了一個鏈接,我看到了答案,但我無法弄清楚。隨着信息給出的,我怎麼能得到它的transition colors

+1

這對我沒有意義:'(1 - 100)* base.getRed())'。乘以-99?真?你不應該硬編碼這些數字,但應該使用過渡變量。你應該用println來測試你的代碼來幫助調試它。 –

+0

考慮創建併發佈一個我們可以不加改變地運行的[最小的,可編譯的,可運行的示例程序](http://stackoverflow.com/help/mcve),它會向我們展示您的問題。 –

回答

10

我花了很多時間試圖找到/創建一個爲我工作的混合算法,這基本上是我能蹣跚起來。

我用這個方法來生成一個漸變過渡混合多種顏色,這表現here

基本上,這種方法允許你設置了一系列的顏色和比例標記,使你獲得更大的控制權指向之間的顏色轉換。

Blend

import java.awt.BorderLayout; 
import java.awt.Color; 
import java.awt.Dimension; 
import java.awt.EventQueue; 
import java.awt.Graphics; 
import java.awt.Graphics2D; 
import java.text.NumberFormat; 
import javax.swing.JFrame; 
import javax.swing.JPanel; 
import javax.swing.JSlider; 
import javax.swing.UIManager; 
import javax.swing.UnsupportedLookAndFeelException; 
import javax.swing.event.ChangeEvent; 
import javax.swing.event.ChangeListener; 

public class ColorFading { 

    public static void main(String[] args) { 
     new ColorFading(); 
    } 

    public ColorFading() { 
     EventQueue.invokeLater(new Runnable() { 
      @Override 
      public void run() { 
       try { 
        UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); 
       } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) { 
       } 

       JFrame frame = new JFrame("Testing"); 
       frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
       frame.setLayout(new BorderLayout()); 
       frame.add(new FadePane()); 
       frame.pack(); 
       frame.setLocationRelativeTo(null); 
       frame.setVisible(true); 
      } 
     }); 
    } 

    public class FadePane extends JPanel { 

     private final float[] fractions = new float[]{0f, 0.5f, 1f}; 
     private final Color[] colors = new Color[]{Color.RED, Color.YELLOW, Color.GREEN}; 
     private float progress = 1f; 
     private JSlider slider; 

     public FadePane() { 
      slider = new JSlider(0, 100); 
      setLayout(new BorderLayout()); 
      add(slider, BorderLayout.SOUTH); 

      slider.addChangeListener(new ChangeListener() { 
       @Override 
       public void stateChanged(ChangeEvent e) { 
        progress = ((float)slider.getValue()/100f); 
        repaint(); 
       } 
      }); 
      slider.setValue(100); 
     } 

     @Override 
     public Dimension getPreferredSize() { 
      return new Dimension(200, 200); 
     } 

     @Override 
     protected void paintComponent(Graphics g) { 
      super.paintComponent(g); 
      Graphics2D g2d = (Graphics2D) g.create(); 
      int width = getWidth(); 
      int height = getHeight(); 
      Color startColor = blendColors(fractions, colors, progress); 
      g2d.setColor(startColor); 
      g2d.fillRect(0, 0, width, height); 
      g2d.dispose(); 
     } 
    } 

    public static Color blendColors(float[] fractions, Color[] colors, float progress) { 
     Color color = null; 
     if (fractions != null) { 
      if (colors != null) { 
       if (fractions.length == colors.length) { 
        int[] indicies = getFractionIndicies(fractions, progress); 

        float[] range = new float[]{fractions[indicies[0]], fractions[indicies[1]]}; 
        Color[] colorRange = new Color[]{colors[indicies[0]], colors[indicies[1]]}; 

        float max = range[1] - range[0]; 
        float value = progress - range[0]; 
        float weight = value/max; 

        color = blend(colorRange[0], colorRange[1], 1f - weight); 
       } else { 
        throw new IllegalArgumentException("Fractions and colours must have equal number of elements"); 
       } 
      } else { 
       throw new IllegalArgumentException("Colours can't be null"); 
      } 
     } else { 
      throw new IllegalArgumentException("Fractions can't be null"); 
     } 
     return color; 
    } 

    public static int[] getFractionIndicies(float[] fractions, float progress) { 
     int[] range = new int[2]; 

     int startPoint = 0; 
     while (startPoint < fractions.length && fractions[startPoint] <= progress) { 
      startPoint++; 
     } 

     if (startPoint >= fractions.length) { 
      startPoint = fractions.length - 1; 
     } 

     range[0] = startPoint - 1; 
     range[1] = startPoint; 

     return range; 
    } 

    public static Color blend(Color color1, Color color2, double ratio) { 
     float r = (float) ratio; 
     float ir = (float) 1.0 - r; 

     float rgb1[] = new float[3]; 
     float rgb2[] = new float[3]; 

     color1.getColorComponents(rgb1); 
     color2.getColorComponents(rgb2); 

     float red = rgb1[0] * r + rgb2[0] * ir; 
     float green = rgb1[1] * r + rgb2[1] * ir; 
     float blue = rgb1[2] * r + rgb2[2] * ir; 

     if (red < 0) { 
      red = 0; 
     } else if (red > 255) { 
      red = 255; 
     } 
     if (green < 0) { 
      green = 0; 
     } else if (green > 255) { 
      green = 255; 
     } 
     if (blue < 0) { 
      blue = 0; 
     } else if (blue > 255) { 
      blue = 255; 
     } 

     Color color = null; 
     try { 
      color = new Color(red, green, blue); 
     } catch (IllegalArgumentException exp) { 
      NumberFormat nf = NumberFormat.getNumberInstance(); 
      System.out.println(nf.format(red) + "; " + nf.format(green) + "; " + nf.format(blue)); 
      exp.printStackTrace(); 
     } 
     return color; 
    } 
} 
5

OK,瘋狂張貼了他的答案(1+與它),我在做這個了,所以我還不如寄我想出了...

import java.awt.*; 
import java.awt.event.*; 
import java.beans.PropertyChangeEvent; 
import java.beans.PropertyChangeListener; 
import java.util.EnumMap; 
import java.util.Map; 
import javax.swing.*; 
import javax.swing.event.*; 

@SuppressWarnings("serial") 
public class ColorTransition extends JPanel { 

    private static final int TRANSITION_DELAY = 30; 
    private static final int PREF_W = 800; 
    private static final int PREF_H = 600; 
    private RgbSliderPanel rgbSliderPanel1 = new RgbSliderPanel("Color 1"); 
    private RgbSliderPanel rgbSliderPanel2 = new RgbSliderPanel("Color 2"); 
    private Color background1; 
    private Color background2; 
    private JButton button = new JButton(new ButtonAction("Push Me")); 

    public ColorTransition() { 
     setBackground(Color.black); 

     add(rgbSliderPanel1.getMainPanel()); 
     add(rgbSliderPanel2.getMainPanel()); 

     add(button); 

     rgbSliderPanel1.addPropertyChangeListener(new PropertyChangeListener() { 

     @Override 
     public void propertyChange(PropertyChangeEvent evt) { 
      if (RgbSliderPanel.COLOR.equals(evt.getPropertyName())) { 
       setBackground(rgbSliderPanel1.calculateColor()); 
      } 
     } 
     }); 
    } 

    @Override 
    public Dimension getPreferredSize() { 
     return new Dimension(PREF_W, PREF_H); 
    } 

    @Override 
    public void setEnabled(boolean enabled) { 
     super.setEnabled(enabled); 
     button.setEnabled(enabled); 
     rgbSliderPanel1.setEnabled(enabled); 
     rgbSliderPanel2.setEnabled(enabled); 
    } 

    private class ButtonAction extends AbstractAction { 

     public ButtonAction(String name) { 
     super(name); 
     } 

     @Override 
     public void actionPerformed(ActionEvent e) { 
     ColorTransition.this.setEnabled(false); 
     background1 = rgbSliderPanel1.calculateColor(); 
     background2 = rgbSliderPanel2.calculateColor(); 

     setBackground(background1); 

     Timer timer = new Timer(TRANSITION_DELAY, new TransitionListener()); 
     timer.start(); 
     } 

     private class TransitionListener implements ActionListener { 
     private int index = 0; 

     @Override 
     public void actionPerformed(ActionEvent e) { 
      if (index > 100) { 
       ((Timer) e.getSource()).stop(); 
       ColorTransition.this.setEnabled(true); 
      } else { 
       int r = (int) (background2.getRed() * index/100.0 + background1 
        .getRed() * (100 - index)/100.0); 
       int g = (int) (background2.getGreen() * index/100.0 + background1 
        .getGreen() * (100 - index)/100.0); 
       int b = (int) (background2.getBlue() * index/100.0 + background1 
        .getBlue() * (100 - index)/100.0); 
       setBackground(new Color(r, g, b)); 
      } 
      index++; 
     } 
     } 
    } 

    private static void createAndShowGui() { 
     JFrame frame = new JFrame("ColorTransition"); 
     frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     frame.getContentPane().add(new ColorTransition()); 
     frame.pack(); 
     frame.setLocationRelativeTo(null); 
     frame.setVisible(true); 
    } 

    public static void main(String[] args) { 
     SwingUtilities.invokeLater(new Runnable() { 
     public void run() { 
      createAndShowGui(); 
     } 
     }); 
    } 
} 

enum Rgb { 
    RED("Red"), GREEN("Green"), BLUE("Blue"); 
    private String name; 

    private Rgb(String name) { 
     this.name = name; 
    } 

    public String getName() { 
     return name; 
    } 
} 

class RgbSliderPanel { 
    public static final String COLOR = "color"; 
    private JPanel mainPanel = new JPanel(); 
    private SwingPropertyChangeSupport propertyChangeSupport = new SwingPropertyChangeSupport(
     this); 
    private Map<Rgb, JSlider> colorSliderMap = new EnumMap<>(Rgb.class); 
    private String name; 
    protected Color color; 

    public RgbSliderPanel(String name) { 
     this.name = name; 
     mainPanel.setBorder(BorderFactory.createTitledBorder(name)); 
     //mainPanel.setOpaque(false); 
     mainPanel.setLayout(new GridLayout(0, 1)); 
     for (Rgb rgb : Rgb.values()) { 
     JSlider colorSlider = new JSlider(0, 255, 0); 
     colorSliderMap.put(rgb, colorSlider); 
     mainPanel.add(colorSlider); 
     colorSlider.setBorder(BorderFactory.createTitledBorder(rgb.getName())); 
     colorSlider.setPaintTicks(true); 
     colorSlider.setPaintTrack(true); 
     colorSlider.setMajorTickSpacing(50); 
     colorSlider.setMinorTickSpacing(10); 
     colorSlider.addChangeListener(new ChangeListener() { 

      @Override 
      public void stateChanged(ChangeEvent e) { 
       Color oldValue = color; 
       Color newValue = calculateColor(); 
       color = newValue; 
       propertyChangeSupport.firePropertyChange(COLOR, oldValue, 
        newValue); 
      } 
     }); 

     } 
    } 

    public JComponent getMainPanel() { 
     return mainPanel; 
    } 

    public void setEnabled(boolean enabled) { 
     for (JSlider slider : colorSliderMap.values()) { 
     slider.setEnabled(enabled); 
     } 
    } 

    public Color calculateColor() { 
     int r = colorSliderMap.get(Rgb.RED).getValue(); 
     int g = colorSliderMap.get(Rgb.GREEN).getValue(); 
     int b = colorSliderMap.get(Rgb.BLUE).getValue(); 
     return new Color(r, g, b); 
    } 

    public String getName() { 
     return name; 
    } 

    public void addPropertyChangeListener(PropertyChangeListener listener) { 
     propertyChangeSupport.addPropertyChangeListener(listener); 
    } 

    public void removePropertyChangeListener(PropertyChangeListener listener) { 
     propertyChangeSupport.removePropertyChangeListener(listener); 
    } 
}