Set Color dynamically based on value Java Swing

后端 未结 3 1900
悲&欢浪女
悲&欢浪女 2020-12-02 03:28

I am using Java Swing. I would like to display colors based on a double values which I compute.

Edit - I need to fill the color of a Path2D object. Cur

3条回答
  •  栀梦
    栀梦 (楼主)
    2020-12-02 03:44

    The question lacks context. All Swing components have the setBackground method which can change the background of opaque components.

    If you want to change the background color of a JTable cell or a JList or a JTable or JComboBox, then you need to provide a custom cell renderer capable of perfoming this task, in which case you should have a look at...

    • JTable, Using Custom Renderers
    • JList, Writing a Custom Cell Renderer
    • JComboBox, Providing a Custom Renderer
    • JTree, Customizing a Tree's Display

    Updated with example, based on updates to the OP's question

    The following is an example of color blending algorithm that allows you to specify the colors you want to use and at what ratio/fraction they should appear. The example is very simply, it uses only three colors spread evenly across the range, but you could put more colors in or adjust the weight according to your requirements.

    The example takes a series of randomly generated values and normalises them, so that as the value tends towards 0 (or the lower normal range) it will get darker, as it approaches 1, it will get lighter.

    You could change the algorithm to normalise positive and negative values separately if you chose.

    Bars

    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 java.util.ArrayList;
    import java.util.List;
    import java.util.Random;
    import javax.swing.JFrame;
    import javax.swing.JPanel;
    import javax.swing.JSpinner;
    import javax.swing.UIManager;
    import javax.swing.UnsupportedLookAndFeelException;
    
    public class ColorBars {
    
        public static void main(String[] args) {
            new ColorBars();
        }
    
        public ColorBars() {
            EventQueue.invokeLater(new Runnable() {
                @Override
                public void run() {
                    try {
                        UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                    } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                        ex.printStackTrace();
                    }
    
                    JFrame frame = new JFrame("Testing");
                    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                    frame.add(new TestPane());
                    frame.pack();
                    frame.setLocationRelativeTo(null);
                    frame.setVisible(true);
                }
            });
        }
    
        public class TestPane extends JPanel {
    
            private PlotPane plotPane;
            private JSpinner valueAdd;
    
            public TestPane() {
                setLayout(new BorderLayout());
                plotPane = new PlotPane();
                add(plotPane);
            }
    
        }
    
        public class PlotPane extends JPanel {
    
            private Color[] colorRange = new Color[]{Color.BLACK, Color.RED, Color.WHITE};
            private float[] ratioRanges = new float[]{0f, 0.5f, 1f};
    
    //        private Color maxColor = Color.WHITE;
    //        private Color minColor = Color.RED;
    
            private List values;
            private double min = Double.MAX_VALUE;
            private double max = Double.MIN_VALUE;
    
            public PlotPane() {
                values = new ArrayList<>(25);
                Random rnd = new Random();
                for (int index = 0; index < 10; index++) {
                    addValue((rnd.nextDouble() * 2000) - 1000);
                }
            }
    
            public void addValue(double value) {
                max = Math.max(max, value);
                min = Math.min(min, value);
                values.add(value);
                repaint();
            }
    
            @Override
            public Dimension getPreferredSize() {
                return new Dimension(200, 200);
            }
    
            @Override
            protected void paintComponent(Graphics g) {
                super.paintComponent(g);
                Graphics g2d = (Graphics2D) g.create();
                int height = getHeight();
                int width = getWidth();
    
                int barWidth = width / values.size();
                int x = 0;
                for (Double value : values) {
                    double norm = value - min;
                    norm /= (max - min);
    
                    int barHeight = (int) (height * norm);
                    System.out.println(NumberFormat.getInstance().format(norm));
                    Color color = blendColors(ratioRanges, colorRange, (float)norm);
                    g2d.setColor(color);
                    g2d.fillRect(x, height - barHeight, barWidth, barHeight);
                    x += barWidth;
                }
                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;
        }
    
    }
    

    You can see this color blend algorithm in use at:

    • Color fading algorithm?
    • Java: Smooth Color Transition

提交回复
热议问题