2 votes

Problème avec une couleur différente du blanc pour créer l'ombre au niveau du JComponent

Je suis en train de développer un nouveau look and feel pour swing et j'ai un problème lorsque je crée une ombre dans le JComponent. Par exemple, lorsque je crée un JButton avec une couleur différente du blanc, l'effet de l'ombre n'est pas correct.

C'est le code comme la création de l'ombre.

protected void paintShadow(@NotNull Graphics g, @NotNull JComponent c){
        int shade = 0;
        int topOpacity = 80;
        int pixels = UIManager.getInt("Button[Default].shadowPixel");
        JButton b = (JButton) c;
        for (int i = 0; i < pixels; i++) {
            g.setColor(new Color(shade, shade, shade, ((topOpacity / pixels) * i)));
            g.drawRoundRect(i, i, b.getWidth() - ((i * 2) + 1), b.getHeight() - ((i * 2) + 1), 7, 7);
        }
    }

et voici le bon effet avec la couleur blanche

enter image description here

et voici le mauvais effet avec l'autre couleur.

enter image description here

Comment puis-je généraliser ma méthode paint shadow ?

Voici un exemple minimal pour ce code

import javax.swing.*;
import javax.swing.plaf.basic.BasicButtonUI;
import java.awt.*;

/**
 * @author https://github.com/vincenzopalazzo
 */
public class MaterialMain extends JFrame {

    static {
        UIManager.put("Button[Default].shadowPixel", 3);
    }

    public void init() {
        JPanel panel = new JPanel();

        JButton witheRightEffect = new JButton("shadow withe");
        witheRightEffect.setUI(new ShadowButtonUI());

        JButton otherColorWrongEffect = new JButton("shadow other color");
        otherColorWrongEffect.setBackground(Color.GREEN);
        otherColorWrongEffect.setUI(new ShadowButtonUI());

        panel.add(witheRightEffect);
        panel.add(otherColorWrongEffect);

        setTitle("Look and feel");

        setDefaultCloseOperation(EXIT_ON_CLOSE);

        setSize(630, 360);

        add(panel);

        setLocationRelativeTo(null);

        setVisible(true);
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                MaterialMain main = new MaterialMain();
                main.init();
            }
        });
    }

    public class ShadowButtonUI extends BasicButtonUI{

        @Override
        public void installUI(JComponent c) {
            super.installUI(c);
            c.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
        }

        @Override
        public void paint(Graphics g, JComponent c) {
            super.paint(g, c);
            paintShadow(g, c);
        }

        protected void paintShadow( Graphics g,  JComponent c){
            int shade = 0;
            int topOpacity = 80;
            int pixels = UIManager.getInt("Button[Default].shadowPixel");
            JButton b = (JButton) c;
            for (int i = 0; i < pixels; i++) {
                g.setColor(new Color(shade, shade, shade, ((topOpacity / pixels) * i)));
                g.drawRoundRect(i, i, b.getWidth() - ((i * 2) + 1), b.getHeight() - ((i * 2) + 1), 7, 7);
            }
        }
    }

}

Le bouton blanc a un effet correct, mais l'ombre du bouton vert est fausse.

enter image description here

0voto

vincenzopalazzo Points 1039

Je veux répondre à cette question, j'ai une solution brute pour créer l'ombre sur le JButton.

Voici le code de ma méthode

public class ShadowButton {
    public static void main(String... args) {
        SwingUtilities.invokeLater(ShadowButton::new);
    }

    public ShadowButton() {
        var fadeWidth = 30;
        var p = new JPanel();
        var b = new JButton("with fading out border!!!") {
            @Override
            public void paintBorder(Graphics g) {
                var rec = g.getClip().getBounds();
                var c = this.getBackground();
                var d = this.getParent().getBackground();
                for (int i = 0; i < fadeWidth; i++) {
                    var col = mixColor(c, d, 1.0 * (i + 1) / fadeWidth);
                    g.setColor(col);
                    g.drawRect(rec.x + i, rec.y + i, rec.width - 2 * i, rec.height - 2 * i);
                }
            }
        };
        b.setFocusable(false);
        b.setBackground(Color.GREEN);
        b.setForeground(Color.BLACK);
        Font f = new Font("Arial", Font.BOLD, 36);
        b.setFont(f);
        b.setBorder(BorderFactory.createLineBorder(b.getBackground(), fadeWidth, false));
        p.setBackground(Color.RED);
        p.add(b);
        var frame = new JFrame("Shadoe Demo");
        frame.setContentPane(p);
        frame.pack();
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    }

    private static Color mixColor(Color c, Color d, double factor) {
        float[] cc = c.getComponents(null);
        float[] dd = d.getComponents(null);
        float[] result = new float[cc.length];
        for (int i = 0; i < 4; i++) {
            result[i] = (float) (factor * cc[i] + (1 - factor) * dd[i]);
        }
        return new Color(result[0], result[1], result[2], result[3]);
    }
}

Ma question portait sur coderanch

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X