2014-01-21 1 views
1

Я пытаюсь сделать health bar, и, как может быть оригинал, он начнет зеленый, и после потери здоровья вы обнаружите, что он станет желтым, затем оранжевым, затем красным .. или что-то относительно этого.Java: Smooth Color Transition

Я попытался с помощью метода, представленного в этой ссылке: https://stackoverflow.com/questions/19841477/java-smooth-color-transition

Результат от этой ссылки был этот код, просто тест от значения 100 до 0, но она закончилась в IllegalArgumentException в нормально Red и Green, и мое предположение по причине того, что по сравнению со значением 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); 
} 

Этот код делает основной переход в определенных точках.

Мне нужно создать поля, чтобы использовать определенную colorsvalues при определенной части health bar, так что теперь у меня есть это ..

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, перед тем Mad отправил свой ответ (и 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); 
    } 
} 

 Смежные вопросы

  • Нет связанных вопросов^_^