Create Custom Radio Buttons in Java Swing

How to Create Custom Radio Buttons with Animations in Java Netbeans

How to Create Custom Radio Buttons with Animations in Java Netbeans




In this Java Tutorial we will see How To Create a collection of five unique custom radio buttons using Java Swing, each with its own distinctive style and smooth animations In Java Using Netbeans.

Project Overview
This project demonstrates Java Swing techniques to create five radio buttons with different styles: Neon, Gradient, Minimal, Cyberpunk,  Neumorphic.
    

What We Are Gonna Use In This Project:

- Java Programming Language.
- NetBeans Editor.





Project Source Code:





/**
 *
 * @author 1BestCsharp
 */
public class RadioButtons_Collection extends JFrame {
    
    // Reference to the currently selected radio button
    private BaseRadioButton selectedButton = null;

    public RadioButtons_Collection(){
            // Set the title of the window
            setTitle("Radio Buttons Collection");
            // Make the application close when the window is closed
            setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            // Set the initial size of the window (width=500, height=600 pixels)
            setSize(550, 600);
            // Center the window on the screen
            setLocationRelativeTo(null);
            
            // Create the main panel that will hold all components
            JPanel mainPanel = new JPanel();
            // Set the layout to stack components vertically
            mainPanel.setLayout(new BoxLayout(mainPanel, BoxLayout.Y_AXIS));
            // Set the background color to dark gray (RGB: 26, 26, 26)
            mainPanel.setBackground(new Color(26, 26, 26));
            // Add a 20-pixel empty border around all sides of the panel
            mainPanel.setBorder(BorderFactory.createEmptyBorder(20, 20, 20, 20));
            
            // Create the radio buttons
            BaseRadioButton neonRadio = new NeonRadioButton();
            BaseRadioButton gradientRadio = new GradientRadioButton();
            BaseRadioButton minimalRadio = new MinimalRadioButton();
            BaseRadioButton cyberpunkRadio = new CyberpunkRadioButton();
            BaseRadioButton neumorphicRadio = new NeumorphicRadioButton();
            
            // Group them (only one can be selected at a time)
            setupRadioGroup(
                    neonRadio, 
                    gradientRadio, 
                    minimalRadio, 
                    cyberpunkRadio,
                    neumorphicRadio
            );
            
            // Add radio button panels with different styles and vertical spacing between them
            mainPanel.add(createRadioButtonPanel("Neon", neonRadio));
            mainPanel.add(Box.createVerticalStrut(30));
            mainPanel.add(createRadioButtonPanel("Gradient", gradientRadio));
            mainPanel.add(Box.createVerticalStrut(30));
            mainPanel.add(createRadioButtonPanel("Minimal", minimalRadio));
            mainPanel.add(Box.createVerticalStrut(30));
            mainPanel.add(createRadioButtonPanel("Cyberpunk", cyberpunkRadio));
            mainPanel.add(Box.createVerticalStrut(30));
            mainPanel.add(createRadioButtonPanel("Neumorphic", neumorphicRadio));
            

            // Add the main panel to the JFrame window
            add(mainPanel);

    }
    
    
    
    // Method to set up the radio button group behavior
    private void setupRadioGroup(BaseRadioButton... radioButtons) {
        for (BaseRadioButton radio : radioButtons) {
            
            radio.addActionListener(e -> {
                // Deselect the previous button
                if (selectedButton != null && selectedButton != radio) {
                    selectedButton.setSelected(false);
                }
                
                // Update the selected button reference
                selectedButton = radio.isSelected() ? radio : null;
                
            });
        }
        
    }
    
    
    // Method that creates a panel containing a label, radio button, and status label
    private JPanel createRadioButtonPanel(String label, JRadioButton radioButton) {
        // Create a new panel to hold the components
        JPanel panel = new JPanel();
        // Use FlowLayout to arrange components horizontally with 20-pixel horizontal gaps
        panel.setLayout(new FlowLayout(FlowLayout.CENTER, 20, 0));
        // Set the panel's background color to dark gray
        panel.setBackground(new Color(26, 26, 26));
        
        
        // Create a label with the specified text
        JLabel nameLabel = new JLabel(label);
        // Set the label's text color to white
        nameLabel.setForeground(Color.WHITE);
        // Set the font to Segoe UI, normal style, 24-point size
        nameLabel.setFont(new Font("Segoe UI", Font.PLAIN, 24));
        // Set a fixed size for the label
        nameLabel.setPreferredSize(new Dimension(140, 30));
        
        // Create a label that will show the radio button state ("Selected" or "Unselected")
        JLabel statusLabel = new JLabel("Unselected");
        // Set the status label's text color to white
        statusLabel.setForeground(Color.WHITE);
        // Set the font to Segoe UI, normal style, 20-point size
        statusLabel.setFont(new Font("Segoe UI", Font.PLAIN, 20));
        // Set a fixed size for the status label
        statusLabel.setPreferredSize(new Dimension(120, 30));
        
        // Check if the radio button is an instance of our custom BaseRadioButton class
        if (radioButton instanceof BaseRadioButton) {
            // Cast the radio button to BaseRadioButton to access its specific methods
            BaseRadioButton baseRadioButton = (BaseRadioButton) radioButton;
            // Set a callback function that updates the status label when the radio button state changes
            baseRadioButton.setStatusUpdateCallback(isSelected -> {
                // Update the text to show "Selected" or "Unselected"
                statusLabel.setText(isSelected ? "Selected" : "Unselected");
                // Change the text color to green when selected, white when unselected
                statusLabel.setForeground(isSelected ? new Color(0, 255, 136) : Color.WHITE);
            });
            
        }

        // Add the components to the panel
        panel.add(nameLabel);
        panel.add(radioButton);
        panel.add(statusLabel);
        
        return panel;
        
    }
    
    
    // Abstract base class for all custom radio buttons
    private abstract class BaseRadioButton extends JRadioButton {
            // Flag to track if the mouse is hovering over the radio button
            protected boolean hover = false;
            // Value between 0.0 (unselected) and 1.0 (selected) for animation progress
            protected float animationProgress = 0.0f;
            // Timer object to handle the animation
            protected Timer animationTimer;
            // Duration of the animation in milliseconds
            protected final int ANIMATION_DURATION = 200;
            // Number of steps in the animation
            protected final int ANIMATION_STEPS = 20;
            // Callback function that will be called when the radio button state changes
            protected CustomRunnable statusUpdateCallback;
            
            // Constructor for the base radio button
            public BaseRadioButton() {
                    // Set the size of the radio button
                    setPreferredSize(new Dimension(70, 70));
                    // Remove the default styling
                    setBorderPainted(false);
                    setFocusPainted(false);
                    setContentAreaFilled(false);

                    // Add a listener to detect when the mouse enters/exits the radio button
                    addMouseListener(new MouseAdapter() {
                        @Override
                        public void mouseEntered(MouseEvent e) {
                            hover = true;
                            repaint();
                        }

                        @Override
                        public void mouseExited(MouseEvent e) {
                            hover = false;
                            repaint();
                        }
                    });

                    // Add a listener to detect when the radio button is clicked
                    addItemListener(e -> {
                        startAnimation(e.getStateChange() == ItemEvent.SELECTED);
                    });
            }
            

            // Method to set the callback function that updates the status label
            public void setStatusUpdateCallback(CustomRunnable callback) {
                this.statusUpdateCallback = callback;
            }
            
            
            // Method to start the animation when the radio button state changes
            protected void startAnimation(boolean targetState) {
                    // Stop any existing animation
                    if (animationTimer != null && animationTimer.isRunning()) {
                        animationTimer.stop();
                    }
                    
                    // Calculate animation parameters
                    final float targetProgress = targetState ? 1.0f : 0.0f;
                    final float startProgress = animationProgress;
                    final float progressStep = (targetProgress - startProgress) / ANIMATION_STEPS;
                    final int delay = ANIMATION_DURATION / ANIMATION_STEPS;

                    // Create a new timer for the animation
                    animationTimer = new Timer(delay, null);
                    animationTimer.addActionListener(new ActionListener() {
                        
                         private int currentStep = 0;
                        
                        @Override
                        public void actionPerformed(ActionEvent e) {
                              currentStep++;

                                if (currentStep <= ANIMATION_STEPS) {
                                    animationProgress = startProgress + (progressStep * currentStep);
                                    repaint();
                                }  else {
                                    animationProgress = targetProgress;
                                    animationTimer.stop();
                                    if (statusUpdateCallback != null) {
                                        statusUpdateCallback.run(targetState);
                                    }
                                }
                          }
                    });
                    
                    // Start the animation timer
                    animationTimer.start();

            }
            
            
            // Interface for the status update callback
            public interface CustomRunnable {
                void run(boolean isSelected);
            }
            

            // Method to blend between two colors based on a ratio (0.0 to 1.0)
            protected Color interpolateColor(Color c1, Color c2, float ratio) {
                int red = Math.round(c1.getRed() * (1 - ratio) + c2.getRed() * ratio);
                int green = Math.round(c1.getGreen() * (1 - ratio) + c2.getGreen() * ratio);
                int blue = Math.round(c1.getBlue() * (1 - ratio) + c2.getBlue() * ratio);
                return new Color(red, green, blue);
            }
    }
    
    
    
    // Neon-style radio button implementation
    private class NeonRadioButton extends BaseRadioButton {
        @Override
        protected void paintComponent(Graphics g) {
            Graphics2D g2 = (Graphics2D) g.create();
            g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
            
            int width = getWidth();
            int height = getHeight();
            int size = Math.min(width, height) - 10;
            int x = (width - size) / 2;
            int y = (height - size) / 2;
            
            // Define colors for unselected and selected states
            Color bgOffColor = new Color(51, 51, 51);
            Color bgOnColor = new Color(0, 255, 136);
            Color currentBgColor = interpolateColor(bgOffColor, bgOnColor, animationProgress);
            
            // Draw the outer circle
            g2.setColor(currentBgColor);
            g2.fill(new Ellipse2D.Float(x, y, size, size));
            
            // Draw inner dot with animation
            if (animationProgress > 0.0f) {
                g2.setColor(Color.WHITE);
                
                // Calculate the size of the inner dot based on animation progress
                float dotSize = size * 0.5f * animationProgress;
                float dotX = x + (size - dotSize) / 2;
                float dotY = y + (size - dotSize) / 2;
                
                g2.fill(new Ellipse2D.Float(dotX, dotY, dotSize, dotSize));
            }
            
            // Add glow effect that increases with animation progress
            int alpha = Math.round(50 * animationProgress);
            if (alpha > 0) {
                g2.setColor(new Color(0, 255, 136, alpha));
                g2.setStroke(new BasicStroke(4));
                g2.draw(new Ellipse2D.Float(x, y, size, size));
            }
            
            g2.dispose();
            
        }
        
    }
    
    
    
    // Gradient-style radio button implementation
    private class GradientRadioButton extends BaseRadioButton {
        @Override
        protected void paintComponent(Graphics g) {
            Graphics2D g2 = (Graphics2D) g.create();
            g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
            
            int width = getWidth();
            int height = getHeight();
            int size = Math.min(width, height) - 10;
            int x = (width - size) / 2;
            int y = (height - size) / 2;
            
            // Define colors for unselected and selected states
            Color offStartColor = new Color(255, 107, 107);
            Color offEndColor = new Color(254, 202, 87);
            Color onStartColor = new Color(72, 52, 212);
            Color onEndColor = new Color(104, 109, 224);
            
            // Calculate the current colors based on animation progress
            Color currentStartColor = interpolateColor(offStartColor, onStartColor, animationProgress);
            Color currentEndColor = interpolateColor(offEndColor, onEndColor, animationProgress);
            
             // Create a gradient and apply it
             GradientPaint gradient = new GradientPaint(
                    x, y, currentStartColor,
                    x + size, y + size, currentEndColor
                );
              g2.setPaint(gradient);
              g2.fill(new Ellipse2D.Float(x, y, size, size));
              
                // Draw inner dot with animation
                if (animationProgress > 0.0f) {
                        g2.setColor(Color.WHITE);

                        // Calculate inner dot size (scales with animation)
                        float dotScale = 0.4f * animationProgress;
                        int dotSize = Math.round(size * dotScale);
                        int dotX = x + (size - dotSize) / 2;
                        int dotY = y + (size - dotSize) / 2;

                        // Add a soft highlight
                        float highlightSize = size * 0.6f;
                        float highlightX = x + (size - highlightSize) / 2;
                        float highlightY = y + (size - highlightSize) / 2;

                        RadialGradientPaint highlight = new RadialGradientPaint(
                            x + size/2, y + size/2, size/2,
                            new float[] {0.0f, 0.7f, 1.0f},
                            new Color[] {
                                new Color(255, 255, 255, 100),
                                new Color(255, 255, 255, 50),
                                new Color(255, 255, 255, 0)
                            }
                        );

                        g2.setPaint(highlight);
                        g2.fill(new Ellipse2D.Float(highlightX, highlightY, highlightSize, highlightSize));

                        // Draw the inner dot
                        g2.setColor(Color.WHITE);
                        g2.fill(new Ellipse2D.Float(dotX, dotY, dotSize, dotSize));

                }
                
                g2.dispose();
            
        }
        
    }
    
    
    
    // Minimal-style radio button implementation
    private class MinimalRadioButton extends BaseRadioButton {
        @Override
        protected void paintComponent(Graphics g) {
            Graphics2D g2 = (Graphics2D) g.create();
            g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
            
            int width = getWidth();
            int height = getHeight();
            int size = Math.min(width, height) - 10;
            int x = (width - size) / 2;
            int y = (height - size) / 2;
            
            // Define colors for unselected and selected states
            Color offColor = Color.WHITE;
            Color onColor = new Color(0, 255, 136);
            Color currentColor = interpolateColor(offColor, onColor, animationProgress);
            
            // Draw the border of the radio button
            g2.setColor(currentColor);
            g2.setStroke(new BasicStroke(2.5f));
            g2.draw(new Ellipse2D.Float(x, y, size, size));
            
            // Draw the inner dot with animation
            if (animationProgress > 0.0f) {
                // Calculate center and sizes
                int centerX = x + size / 2;
                int centerY = y + size / 2;
                
                // Calculate inner dot size (scales with animation)
                float dotScale = 0.5f * animationProgress;
                int dotSize = Math.round(size * dotScale);
                int dotX = centerX - dotSize / 2;
                int dotY = centerY - dotSize / 2;
                
                // Draw dot
                g2.setColor(currentColor);
                g2.fill(new Ellipse2D.Float(dotX, dotY, dotSize, dotSize));
                
            }
            
            g2.dispose();
            
        }

    }
    
    // Cyberpunk-style radio button implementation
    private class CyberpunkRadioButton extends BaseRadioButton {
        @Override
        protected void paintComponent(Graphics g) {
            Graphics2D g2 = (Graphics2D) g.create();
            g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
            
            int width = getWidth();
            int height = getHeight();
            int size = Math.min(width, height) - 10;
            int x = (width - size) / 2;
            int y = (height - size) / 2;
            
            // Define center point
            int centerX = x + size/2;
            int centerY = y + size/2;
            
            // Draw the dark background circle
            g2.setColor(new Color(15, 15, 22));
            g2.fill(new Ellipse2D.Float(x, y, size, size));
            
            // Define colors for the cyberpunk theme
            Color magenta = new Color(255, 0, 139);
            Color cyan = new Color(0, 255, 255);
            Color yellow = new Color(255, 211, 0);
            
            // Draw tech pattern inside (circuitry look)
            g2.setColor(new Color(30, 30, 40));
            g2.setStroke(new BasicStroke(1f));
            
            // Draw circular rings
            g2.drawOval(x + size/4, y + size/4, size/2, size/2);
            g2.drawOval(x + size/8, y + size/8, size*3/4, size*3/4);
            
            // Draw crosshair lines
            g2.drawLine(centerX, y + 5, centerX, y + size - 5);
            g2.drawLine(x + 5, centerY, x + size - 5, centerY);
            
            // Add circuit node points at intersections
            g2.setColor(new Color(50, 50, 70));
            int nodeSize = 3;
            // Center node
            g2.fillRect(centerX - nodeSize/2, centerY - nodeSize/2, nodeSize, nodeSize);
            // Nodes at the four directions
            g2.fillRect(centerX - nodeSize/2, y + size/4 - nodeSize/2, nodeSize, nodeSize);
            g2.fillRect(centerX - nodeSize/2, y + size*3/4 - nodeSize/2, nodeSize, nodeSize);
            g2.fillRect(x + size/4 - nodeSize/2, centerY - nodeSize/2, nodeSize, nodeSize);
            g2.fillRect(x + size*3/4 - nodeSize/2, centerY - nodeSize/2, nodeSize, nodeSize);
            
            // Active circuit effect when selected or hovering
            if (animationProgress > 0.0f || hover) {
                float alpha = hover ? Math.max(0.3f, animationProgress) : animationProgress;
                
                // Draw glowing circuit paths
                g2.setStroke(new BasicStroke(1.5f));
                g2.setColor(new Color(cyan.getRed(), cyan.getGreen(), cyan.getBlue(), (int)(180 * alpha)));
                
                // Glowing circular rings
                g2.drawOval(x + size/4, y + size/4, size/2, size/2);
                g2.drawOval(x + size/8, y + size/8, size*3/4, size*3/4);
                
                // Glowing crosshair
                g2.drawLine(centerX, y + 5, centerX, y + size - 5);
                g2.drawLine(x + 5, centerY, x + size - 5, centerY);
                
                // Create a subtle inner glow using gradient paint
                if (animationProgress > 0) {
                    Color innerGlowStart = new Color(magenta.getRed(), 
                            magenta.getGreen(), 
                            magenta.getBlue(), 
                            (int)(40 * animationProgress)
                    );
                    Color innerGlowEnd = new Color(cyan.getRed(), 
                            cyan.getGreen(), 
                            cyan.getBlue(),
                            (int)(40 * animationProgress)
                    );
                    
                    RadialGradientPaint glowGradient = new RadialGradientPaint(
                        centerX, centerY, size/2,
                        new float[] {0.0f, 0.8f},
                        new Color[] {innerGlowStart, innerGlowEnd}
                    );

                    g2.setPaint(glowGradient);
                    g2.fill(new Ellipse2D.Float(x + 2, y + 2, size - 4, size - 4)); 
                }
                
            }
            
            
            // Draw border
            Color borderColor1, borderColor2;
            if (animationProgress > 0.0f) {
                borderColor1 = magenta;
                borderColor2 = cyan;
            } else {
                borderColor1 = new Color(70, 70, 90);
                borderColor2 = new Color(120, 120, 140);
            }
            
            // Create two-tone border effect with gradient
            RadialGradientPaint gradientBorder = new RadialGradientPaint(
                centerX, centerY, size/2,
                new float[] {0.7f, 1.0f},
                new Color[] {borderColor1, borderColor2}
            );

            g2.setPaint(gradientBorder);
            g2.setStroke(new BasicStroke(2.5f));
            g2.draw(new Ellipse2D.Float(x, y, size, size));
            
            // Adding cyberpunkish yellow corner accents
            int accentSize = 5;
            g2.setColor(yellow);
            g2.setStroke(new BasicStroke(1.5f));
            // Top accent
            g2.drawLine(centerX - accentSize, y, centerX + accentSize, y);
            // Bottom accent
            g2.drawLine(centerX - accentSize, y + size, centerX + accentSize, y + size);
            // Left accent
            g2.drawLine(x, centerY - accentSize, x, centerY + accentSize);
            // Right accent
            g2.drawLine(x + size, centerY - accentSize, x + size, centerY + accentSize);
            
            // Draw the inner dot for selected state
            if (animationProgress > 0.0f) {
                // Create a random seed for consistent yet randomized glitch effect
                Random rand = new Random(System.currentTimeMillis() / 1000);
                int glitchFactor = 2;
                
                // Inner dot size calculation
                float dotSize = size * 0.4f * animationProgress;
                float dotX = centerX - dotSize/2;
                float dotY = centerY - dotSize/2;
                
                // Draw glitchy inner dots with offset shadows
                // Cyan dot shadow
                g2.setColor(new Color(cyan.getRed(), 
                        cyan.getGreen(), cyan.getBlue(), (int)(200 * animationProgress)));
                g2.fill(new Ellipse2D.Float(
                    dotX + rand.nextInt(glitchFactor) - glitchFactor/2,
                    dotY + rand.nextInt(glitchFactor) - glitchFactor/2,
                    dotSize, dotSize
                ));
                
                // Magenta dot shadow
                g2.setColor(new Color(magenta.getRed(), 
                        magenta.getGreen(), magenta.getBlue(), (int)(150 * animationProgress)));
                g2.fill(new Ellipse2D.Float(
                    (dotX - 2) + rand.nextInt(glitchFactor) - glitchFactor/2,
                    (dotY + 2) + rand.nextInt(glitchFactor) - glitchFactor/2,
                    dotSize, dotSize
                ));
                
                // Main white inner dot
                g2.setColor(new Color(255, 255, 255, (int)(255 * animationProgress)));
                g2.fill(new Ellipse2D.Float(dotX, dotY, dotSize, dotSize));
                
                // Add scanline effect
                g2.setColor(new Color(255, 255, 255, 20));
                g2.setStroke(new BasicStroke(1f));
                for (int i = 0; i < size; i += 4) {
                    g2.drawLine(x, y + i, x + size, y + i);
                }

            }
            
            g2.dispose();
            
        }
        
    }
    
    
    
    // Neumorphic-style radio button implementation
    private class NeumorphicRadioButton extends BaseRadioButton {
        
        @Override
        protected void paintComponent(Graphics g) {
            Graphics2D g2 = (Graphics2D) g.create();
            g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, 
                    RenderingHints.VALUE_ANTIALIAS_ON);

            int width = getWidth();
            int height = getHeight();
            int size = Math.min(width, height) - 10;
            int x = (width - size) / 2;
            int y = (height - size) / 2;

            // Define the colors for the neumorphic effect
            Color baseColor = new Color(26, 26, 26);
            Color lightShadow = new Color(40, 40, 40);
            Color darkShadow = new Color(10, 10, 10);

            // Draw the base shape (slightly inset circle)
            g2.setColor(baseColor);
            g2.fill(new Ellipse2D.Float(x, y, size, size));

            // Draw shadows to create the neumorphic effect
            // Light shadow on top-left
            g2.setColor(lightShadow);
            g2.setStroke(new BasicStroke(2f));
            g2.draw(new Arc2D.Float(x, y, size, size, 45, 180, Arc2D.OPEN));

            // Dark shadow on bottom-right
            g2.setColor(darkShadow);
            g2.setStroke(new BasicStroke(2f));
            g2.draw(new Arc2D.Float(x, y, size, size, 225, 180, Arc2D.OPEN));

            // Draw the inner area
            g2.setColor(new Color(22, 22, 22));
            g2.fill(new Ellipse2D.Float(x + 4, y + 4, size - 8, size - 8));

            // Colors for selected state
            Color onStartColor = new Color(0, 255, 136);
            Color onEndColor = new Color(0, 204, 106);

            // Draw inner dot when selected
            if (animationProgress > 0.0f) {
                // Apply a soft glow based on selected state
                Color glowColor = interpolateColor(baseColor, onStartColor, animationProgress * 0.5f);
                g2.setColor(glowColor);
                g2.fill(new Ellipse2D.Float(x + 6, y + 6, size - 12, size - 12));
                
                // Draw the inner dot
                float dotScale = 0.4f * animationProgress;
                // Ensure dotSize is at least 1 pixel to avoid zero radius
                int dotSize = Math.max(1, Math.round(size * dotScale));
                int dotX = x + (size - dotSize) / 2;
                int dotY = y + (size - dotSize) / 2;
                
                // Create gradient for inner dot
                // Ensure radius is at least 0.5f to avoid "Radius must be greater than zero" exception
                float gradientRadius = Math.max(0.5f, dotSize / 2f);

                RadialGradientPaint dotGradient = new RadialGradientPaint(
                    x + size/2, y + size/2, gradientRadius,
                    new float[] {0.0f, 1.0f},
                    new Color[] {
                        interpolateColor(baseColor, onStartColor, animationProgress),
                        interpolateColor(baseColor, onEndColor, animationProgress)
                    }
                );
                
                g2.setPaint(dotGradient);
                g2.fill(new Ellipse2D.Float(dotX, dotY, dotSize, dotSize));

            }
            
            g2.dispose();
            
        }
        
    }
    
    
    // Main method
    public static void main(String[] args) {
        SwingUtilities.invokeLater(() -> {
            try {
                UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
            } catch (Exception e) {
                e.printStackTrace();
            }
            // Create and display the application
            new RadioButtons_Collection().setVisible(true);
        });
    }
    
    
}
  



The Final Result:

Create Custom Radio Buttons in Java Swing 1

Create Custom Radio Buttons in Java Swing 2