0

I have two classes, one where I create the frame and all the other things, and the class "RoundedButton", that is extended to JButton, where I modify the buttons in order to make it Rounded. When I run the programme and hover the mouse over the button the bottom background disappears. This is the class RoundedBotton:

public class RoundedButton extends JButton {
private Color backgroundColor;
private Color foregroundColor;
private Color hoverBackgroundColor;

    public RoundedButton(String label, Color backgroundColor, Color foregroundColor) {
        super(label);
        this.backgroundColor = backgroundColor;
        this.foregroundColor = foregroundColor;
        this.hoverBackgroundColor = backgroundColor.darker();
        setBorderPainted(false);
        setBackground(backgroundColor);
        setForeground(foregroundColor);
        addMouseListener(new MouseAdapter() {
            @Override
            public void mouseEntered(MouseEvent e) {
                setBackground(hoverBackgroundColor);
            }
    
            @Override
            public void mouseExited(MouseEvent e) {
                setBackground(backgroundColor);
            }
        });
    }
    
    @Override
    protected void paintComponent(Graphics g) {
        Graphics2D g2 = (Graphics2D) g;
        g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
        RoundRectangle2D.Float roundRect = new RoundRectangle2D.Float(0, 0, getWidth(), getHeight(), 50, 50);
        g2.clip(roundRect);
        super.paintComponent(g2);
    }
    
    @Override
    protected void paintBorder(Graphics g) {
        g.setColor(backgroundColor);
        g.drawRoundRect(0, 0, getWidth()-1, getHeight()-1, 50, 50);
    }
}

This is the method, where I create the frame and all other stuff:

    void create(){ 
        JFrame f = new JFrame("Rubrica"); 
        f.setSize(600,750); 
        f.setResizable(false);
        Font titFont = new Font("Oswald", Font.PLAIN,35);     //Font per il titolo
        Color bgColor = Color.decode("#333b41");
        Color bColor = Color.decode("#202329");
        Color cancColor = Color.decode("#f42244");
        Color newColor = Color.decode("#2dc05f");
    
        JPanel p = new JPanel(new BorderLayout());
        f.add(p);
        //useless code
        JPanel pButton = new JPanel(new GridLayout(1,2,10,10));
        pButton.setPreferredSize(new Dimension(600,80));
        pButton.setBackground(bColor);
        p.add(pButton, BorderLayout.SOUTH);
    
        RoundedButton insert = new RoundedButton("Insert", newColor, Color.white);
        RoundedButton delete = new RoundedButton("Delete", cancColor, Color.white);
    
        pButton.add(insert);
        pButton.add(delete);
    
        f.setVisible(true);
        f.setDefaultCloseOperation(EXIT_ON_CLOSE);
}

I expect to hover themouse over the buttons and still see the colour of the panel where it is posizionated

damby
  • 3
  • 1

1 Answers1

1

So, on MacOS, you're "roll over" workflow doesn't work for me AND, it also paints the focus rectangle, which isn't pretty...

enter image description here

So, instead of doing this...

setBackground(backgroundColor);
setForeground(foregroundColor);
addMouseListener(new MouseAdapter() {
    @Override
    public void mouseEntered(MouseEvent e) {
        setBackground(hoverBackgroundColor);
    }

    @Override
    public void mouseExited(MouseEvent e) {
        setBackground(backgroundColor);
    }
});

I would instead make use of the "roll over" support which already exists and change your class to something more like...

public class RoundedButton extends JButton {
    private Color hoverBackgroundColor;

    public RoundedButton(String label, Color backgroundColor, Color foregroundColor) {
        super(label);
        this.hoverBackgroundColor = backgroundColor.darker();
        
        setBackground(backgroundColor);
        setForeground(foregroundColor);
        setBorderPainted(false);
        setFocusPainted(false);
        setOpaque(false);
        setRolloverEnabled(true);
    }

    @Override
    protected void paintComponent(Graphics g) {
        Graphics2D g2 = (Graphics2D) g;
        g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);

        ButtonModel model = getModel();

        RoundRectangle2D.Float roundRect = new RoundRectangle2D.Float(0, 0, getWidth(), getHeight(), 50, 50);
        // This kind of thing always freaks me out - but that's me
        //g2.clip(roundRect);
        if (model.isRollover()) {
            g2.setColor(hoverBackgroundColor);
        } else {
            g2.setColor(getBackground());
        }
        g2.fill(roundRect);

        super.paintComponent(g2);
    }

    @Override
    protected void paintBorder(Graphics g) {
        g.setColor(getBackground());
        g.drawRoundRect(0, 0, getWidth() - 1, getHeight() - 1, 50, 50);
    }
}

enter image description here

Oh, and calling setPreferredSize is a really bad idea

MadProgrammer
  • 343,457
  • 22
  • 230
  • 366
  • This work really well, but I wonder why calling setPreffereSize is a bad idea? – damby Mar 08 '23 at 07:31
  • 1
    @damby Because you're removing all ability for the component to make decisions about how best it would like to be displayed. It's also possible to have other piece of code call this as well, I can't tell you the hours I've wasted tearing my hair out over trying to figure out why a layout won't work only to discover some obscure, buried piece of code call `setPreferredSize` – MadProgrammer Mar 08 '23 at 10:08
  • @damby _but I wonder why calling setPreffereSize is a bad idea_ well, I wonder why your research didn't come up with https://stackoverflow.com/questions/7229226/should-i-avoid-the-use-of-setpreferredmaximumminimumsize-methods-in-java-swi/7229519#7229519 :) – kleopatra Mar 08 '23 at 12:04