1

Once I hover over any of the round buttons a square background appears behind it and never disappears again. The button is still clickable while the square background isn't. I haven't implemented any MouseEvents so I have no idea why the background appears

https://i.stack.imgur.com/I1MIq.png left: after it's been clicked, center: after mouseover, right: original state

Code Sample

import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.*;

public class GUI implements ActionListener {
    private JLabel textLabel;
    private JButton buttonL, buttonConfirm, buttonR;
    
    public GUI() {
        JPanel mainDisplay = new JPanel();
        mainDisplay.setBackground(new Color(172, 181, 176));
        mainDisplay.setPreferredSize(new Dimension(150, 160));
        mainDisplay.setLayout(new BorderLayout());
        textLabel = new JLabel("1");
        textLabel.setHorizontalAlignment(SwingConstants.CENTER);
        mainDisplay.add(textLabel, BorderLayout.CENTER);
        
        JPanel container = new JPanel();
        container.setLayout(new GridBagLayout());
        GridBagConstraints gc = new GridBagConstraints();
        gc.gridwidth = GridBagConstraints.REMAINDER;
        gc.insets = new Insets(75, 0, 0, 0);
        container.add(mainDisplay, gc);
        
        Dimension buttonDimension = new Dimension(18, 18);
        Color buttonColor = new Color(242, 240, 241);
        buttonL = new RoundButton();
        buttonL.setBackground(buttonColor);
        buttonL.setPreferredSize(buttonDimension);
        buttonL.addActionListener(this);
        gc.gridwidth = GridBagConstraints.RELATIVE;
        gc.insets = new Insets(10, 20, 0, 0);
        container.add(buttonL, gc);
        
        buttonConfirm = new RoundButton();
        buttonConfirm.setBackground(buttonColor);
        buttonConfirm.setPreferredSize(buttonDimension);
        buttonConfirm.addActionListener(this);
        gc.insets = new Insets(40, -35, 0, 0);
        container.add(buttonConfirm, gc);
        
        buttonR = new RoundButton();
        buttonR.setBackground(buttonColor);
        buttonR.setPreferredSize(buttonDimension);
        buttonR.addActionListener(this);
        gc.insets = new Insets(10, -50, 0, 0);
        container.add(buttonR, gc);
        
        JFrame frame = new JFrame();
        frame.add(container);
        frame.pack();
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    }
    
    @Override
    public void actionPerformed(ActionEvent e) {
        if(e.getSource() == buttonL) {
            textLabel.setText("L");;
        } else if(e.getSource() == buttonConfirm) {
            textLabel.setText("");
        } else if(e.getSource() == buttonR) {
            textLabel.setText("R");
        }
    }
    
    public static void main(String[] args) {        
            new GUI();
    }
}

Round JButton

import java.awt.Color;
import java.awt.Graphics;
import java.awt.Shape;
import java.awt.geom.Ellipse2D;
import javax.swing.JButton;

public class RoundButton extends JButton {
    Shape shape;
    
    @Override
    protected void paintComponent(Graphics g) {
        g.setColor(getBackground());
        g.fillOval(0, 0, getSize().width - 1, getSize().height - 1);
    }

    @Override
    protected void paintBorder(Graphics g) {
        g.setColor(Color.darkGray);
        g.drawOval(0, 0, getSize().width - 1, getSize().height - 1);
    }

    @Override
    public boolean contains(int x, int y) {
        if (shape == null || !shape.getBounds().equals(getBounds())) {
            shape = new Ellipse2D.Float(0, 0, getWidth(), getHeight());
        }
        return shape.contains(x, y);
    }
}
Egg
  • 13
  • 3
  • 1
    1) For better help sooner, [edit] to add a [MCVE] or [Short, Self Contained, Correct Example](http://www.sscce.org/). 2) One way to get image(s) for an example is to hot link to images seen in [this Q&A](http://stackoverflow.com/q/19209650/418556). E.G. The code in [this answer](https://stackoverflow.com/a/10862262/418556) hot links to an image embedded in [this question](https://stackoverflow.com/q/10861852/418556). 3) Java GUIs have to work on different OS', screen size, screen resolution etc. using different PLAFs in different locales. As such, they are not conducive to pixel .. – Andrew Thompson Jul 13 '21 at 12:29
  • 1
    .. perfect layout. Instead use layout managers, or [combinations of them](http://stackoverflow.com/a/5630271/418556) along with layout padding and borders for [white space](http://stackoverflow.com/a/17874718/418556). 4) A `JButton` can swap icons on focus, mouse over, pressed etc. Why try to implement your own solution? 5) Why the fascination with round buttons? A rectangular button works every bit as well (*better*, from what you've described). – Andrew Thompson Jul 13 '21 at 12:32

1 Answers1

3

When doing custom painting the basic code should be:

public void paintComponent(Graphics g)
{
    super.paintComponent(g);

    // add custom painting here
}

This will make sure the background is cleared so there are no painting artifacts.

However, in your case you want the background of the parent panel to be painted before the button is painted so you need to use:

button.setOpaque(false);

Also, when you click on a button the rectangle will still appear indicating the button is in a pressed state. To remove this painting you need to use:

button.setContentAreaFilled( false );

Check out: Change JButton focus area for another implementation of a round button.

camickr
  • 321,443
  • 19
  • 166
  • 288