/ / Java: Smooth Color Transition - Java, Animation, Farben, Übergänge

Java: Smooth Color Transition - Java, Animation, Farben, Übergänge

Ich versuche es zu machen health barund als was ursprünglich sein könnte, wird es grün anfangen, und nachdem Sie Ihre Gesundheit verloren haben, werden Sie feststellen, dass es gelb, dann orange, dann rot wird ... oder etwas in Bezug darauf.

Ich habe versucht, die in diesem Link angegebene Methode zu verwenden: https://stackoverflow.com/questions/19841477/java-smooth-color-transition

Das Ergebnis dieses Links war dieser Code, nur ein Test von Wert 100 bis 0, der jedoch mit einem endete IllegalArgumentException normalerweise Red und Greenund ich vermute aus gutem Grund, dass es über dem Wert von 255 liegt.

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

Es hat nicht wirklich funktioniert und ich habe absolut keine Ahnung, wie ich es erreichen kann transition so wie ich es mir wünsche.

Also in meinem HealthBar Klasse, ich habe eine update() Methode

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

Dieser Code führt an bestimmten Stellen einen grundlegenden Übergang durch.

Ich muss Felder erstellen, um bestimmte zu verwenden colors bestimmt values des health bar, also jetzt habe ich das ..

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

Ich werde nur ein Beispiel für das letzte Stück verwenden.

Also weiß ich, dass ich eine haben werde color dass ich gehe, und a color das ist eine Basis. Ich bin mir nicht so sicher, ob ich eine brauche color für Strom. Das Problem, das ich jetzt sehe, betrifft die Schritte des Übergangs, da jeder Übergang eine andere Anzahl von Schritten hat.

Zusammenfassung und Frage
Ich weiß nicht, wie ich das erreichen soll, was ich versuche. Ich weiß nur, dass ich ein Ziel und eine Basis brauche colorund ich lieferte einen Link zu einer Antwort, die ich sah, aber ich konnte es nicht wirklich herausfinden. Wie konnte ich mit den gegebenen Informationen dazu kommen? transition colors ?

Antworten:

11 für die Antwort № 1

Ich habe viel Zeit damit verbracht, einen Mischalgorithmus zu finden / zu erstellen, der für mich funktioniert. Dies ist im Grunde das, was ich zusammen humpeln konnte.

Ich habe diesen Ansatz verwendet, um einen Gradientenübergang zu erzeugen, der mehrere Farben mischt, wie gezeigt Hier

Grundsätzlich können Sie mit diesem Ansatz eine Reihe von Farben und Prozentmarkierungen einrichten, um eine viel bessere Kontrolle darüber zu erhalten, zwischen welchen Punkten die Farben wechseln.

Mischung

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 für die Antwort № 2

OK, Vor Mad hat seine Antwort gepostet (und 1+ darauf), ich habe auch daran gearbeitet, also könnte ich genauso gut posten, was ich mir ausgedacht habe ...

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