Java - Show And Hide Passwords in JTable

How to Show And Hide Password Inside a JTable Cell In Java Netbeans

How to Show And Hide Password Inside a JTable Cell In Java Netbeans


In this Java Tutorial we will see How To Create a JTable allowing the user to toggle the visibility of passwords using a checkbox in the "Show-Password" column. In Java Using Netbeans.

What We Are Gonna Use In This Project:

- Java Programming Language.
- NetBeans Editor.





Project Source Code:


package new_tutorials;

import java.awt.Component;
import java.awt.Font;
import javax.swing.AbstractCellEditor;
import javax.swing.JCheckBox;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.SwingConstants;
import javax.swing.table.AbstractTableModel;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.TableCellEditor;

/**
 *
 * @author 1BestCsharp
 */
public class PasswordTableFrame extends JFrame{

    public PasswordTableFrame(){
        
        setTitle("Password Table Frame");
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setSize(600,400);
        setLocationRelativeTo(null);
        
        initializeUI();
        
    }
    
    private void initializeUI(){
        // Create a table with a custom table model
        JTable table = new JTable(new PasswordTableModel());
        
        // Set custom cell renderer and editor for the "Show Password" column
        table.getColumnModel().getColumn(2).setCellRenderer(new CheckBoxRenderer());
        table.getColumnModel().getColumn(2).setCellEditor(new CheckboxEditor());
        
        table.setFont(new Font("Arial",Font.PLAIN,22));
        table.setRowHeight(50);
        
        JScrollPane scrollPane = new JScrollPane(table);
        add(scrollPane);
    }
    
    public static void main(String[] args) {
        PasswordTableFrame frame = new PasswordTableFrame();
        frame.setVisible(true);
    }
    
    // Create a custom table model to handle password display
    private class PasswordTableModel extends AbstractTableModel{

        private final String[] columnNames = {"Username","Password","Show-Password"};
        private final Object[][] data = {
                {"user1", "password1", false},
                {"user2", "password2", false},
                {"user3", "password3", false},
                {"user4", "password4", false},
                {"user5", "password5", false}
        };
        
        @Override
        public int getRowCount() { return data.length; }

        @Override
        public int getColumnCount() { return columnNames.length; }

        @Override
        public Object getValueAt(int rowIndex, int columnIndex) {
        // Hide the password if "Show Password" is unchecked
            if(columnIndex == 1 && ! (boolean) data[rowIndex][2]){
                return "**********";
            }
            
            else{ return data[rowIndex][columnIndex]; }
            
        }
        
        @Override
        public String getColumnName(int columnIndex){
            return columnNames[columnIndex];
        }
        
        @Override
        public boolean isCellEditable(int rowIndex, int columnIndex){
            return columnIndex == 2;
        }
        
        
        @Override
        public void setValueAt(Object value, int rowIndex, int columnIndex){
            // Update the "Password" column when "Show Password" checkbox is modified
            if(columnIndex == 2){
                data[rowIndex][columnIndex] = value;
                fireTableCellUpdated(rowIndex, columnIndex - 1);
            }
        }
        
    }
    
    
    // Create a custom cell renderer for the checkbox
    private class CheckBoxRenderer extends DefaultTableCellRenderer{
        private final JCheckBox checkBox = new JCheckBox();
        
        public CheckBoxRenderer(){
         
            checkBox.setHorizontalAlignment(SwingConstants.CENTER);
            
        }
        
        @Override
        public Component getTableCellRendererComponent(JTable table, Object value, boolean  isSelected, boolean hasFocus, int row, int column){
            
            checkBox.setSelected((boolean)value);
            return checkBox;
            
        }
    }
    
    
    // Create a custom cell editor for the checkbox
    private class CheckboxEditor extends AbstractCellEditor implements TableCellEditor{

        private final JCheckBox checkBox = new JCheckBox();
        
        public CheckboxEditor(){
            checkBox.addActionListener(e -> stopCellEditing());
            checkBox.setHorizontalAlignment(SwingConstants.CENTER);
        }
        
        @Override
        public Object getCellEditorValue() {
            
            return checkBox.isSelected();
            
        }

        @Override
        public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column) {
        
            checkBox.setSelected((boolean) value);
            return checkBox;
            
        }
        
    }
  
}


The Final Result:

Password Inside a JTable Cell In Java

Show Password Inside a JTable Cell In Java

Show And Hide Password Inside a JTable Cell In Java








5 Custom Radio Buttons In Python Tkinter

How to Create Custom Radio Buttons With Different Styles in Python Tkinter

How to Create Beautiful Custom Radio Buttons in Python Tkinter




In this Python Tutorial we will see How to Create five completely different radio button styles using Python's tkinter and PIL libraries.

What We Will Do?
- Create a flexible base class for custom radio buttons.
- Implement smooth animations and hover effects.
- Build five distinct radio button styles.
- Handle radio button groups with proper selection logic.
- Use PIL for high-quality anti-aliased graphics.

What We Are Gonna Use In This Project:

- Python Programming Language.
- Tkinter (GUI).
- VS Editor.






Project Source Code:




import tkinter as tk
from PIL import Image, ImageTk, ImageDraw, ImageFilter

# ========================================================================
# Base class for all radio button styles
# This class defines common functionality that all radio button styles will share
# ========================================================================
class RadioButton(tk.Canvas):
def __init__(self, parent, width=30, height=30, group=None,
value=None, command=None):
# Initialize canvas with specified dimensions and appearance
# A canvas is a widget where we can draw shapes, images, etc.
super().__init__(parent, width=width, height=height,
highlightthickness=0, bd=0, bg="#1A1A1A")
# Store parameters for later use
self.width = width # Width of the radio button
self.height = height # Height of the radio button
self.group = group # RadioGroup this button belongs to (for grouped behavior)
self.value = value # Value associated with this button (returned when selected)
self.command = command # Function to call when button is selected
# State tracking variables
self.is_selected = False # Tracks if this button is currently selected
self.hover = False # Tracks if mouse is hovering over this button
self.animation_progress = 0.0 # Animation state (0.0 = off, 1.0 = fully on)
self.animation_running = False # Tracks if animation is currently running
# Animation configuration - controls how smooth transitions look
self.animation_duration = 0.2 # Total time for animation in seconds
self.animation_steps = 15 # Number of steps in animation
# Time per step
self.animation_step_time = self.animation_duration / self.animation_steps
# Bind mouse events - these detect when user interacts with the button
self.bind("<ButtonPress-1>", self.on_click) # Detect mouse clicks
self.bind("<Enter>", self.on_enter) # Detect when mouse enters button area
self.bind("<Leave>", self.on_leave) # Detect when mouse leaves button area

# Register with group if provided - this allows for radio button group behavior
# where only one button in a group can be selected
if self.group is not None:
self.group.add_radio(self)
# Initial draw - show the button in its starting state
self.draw()
def on_click(self, event=None):
# Handle click event - select this button
if self.group is not None:
# If button is part of a group, let the group handle selection logic
self.group.select(self)
else:
# Otherwise, handle selection directly
self.select()

def on_enter(self, event):
# Mouse entered button area - show hover effect
self.hover = True
self.draw() # Redraw with hover effect

def on_leave(self, event):
# Mouse left button area - remove hover effect
self.hover = False
self.draw() # Redraw without hover effect
def select(self):
# Select this button if it's not already selected
if not self.is_selected:
self.is_selected = True # Mark as selected
self.start_animation() # Begin animation to selected state
if self.command:
# Call command function with button's value if one was provided
self.command(self.value)

def deselect(self):
# Deselect this button if it's currently selected
if self.is_selected:
self.is_selected = False # Mark as deselected
self.start_animation() # Begin animation to deselected state


def start_animation(self):
# Begin animating between states (selected/deselected)
# If animation is already running, do nothing
if self.animation_running:
return

self.animation_running = True
# Determine target state and setup animation
# If selected, animate toward 1.0, otherwise toward 0.0
target_progress = 1.0 if self.is_selected else 0.0
start_progress = self.animation_progress # Store current progress
step = 0 # Initialize step counter
# This nested function will be called repeatedly to animate the button
def animate():
nonlocal step # Use the step variable from outer function
if step < self.animation_steps:
# Calculate current progress in animation
progress_delta = (target_progress-start_progress)/self.animation_steps
self.animation_progress = start_progress + (progress_delta * step)
step += 1
self.draw() # Redraw with current animation state
# Schedule next animation step using Tkinter's after method
# This creates a smooth animation by spacing out the updates
self.after(int(self.animation_step_time * 1000), animate)
else:
# Animation complete - set final state
self.animation_progress = target_progress
self.draw()
self.animation_running = False
# Start animation by calling the animate function
animate()
def interpolate_color(self, color1, color2, ratio):
# Blend two hex colors based on ratio (0.0 to 1.0)
# This creates smooth transitions between colors
# Extract RGB components from hex color strings
r1, g1, b1 = int(color1[1:3], 16), int(color1[3:5], 16), int(color1[5:7], 16)
r2, g2, b2 = int(color2[1:3], 16), int(color2[3:5], 16), int(color2[5:7], 16)
# Calculate interpolated RGB values
r = int(r1 * (1 - ratio) + r2 * ratio)
g = int(g1 * (1 - ratio) + g2 * ratio)
b = int(b1 * (1 - ratio) + b2 * ratio)
# Return the new color as a hex string
return f'#{r:02x}{g:02x}{b:02x}'
def create_circle(self, x, y, radius, **kwargs):
# Function to create a circle on the canvas
# A circle is actually an oval with equal width and height in Tkinter
return self.create_oval(x-radius, y-radius, x+radius, y+radius, **kwargs)

def create_smooth_image(self, width, height, draw_func):
# Create a high-quality anti-aliased image using PIL (Python Imaging Library)
# This gives smoother graphics than Tkinter's built-in drawing
# Create image at higher resolution
scale_factor = 2 # Create at 2x size and scale down for better quality
img_width = width * scale_factor
img_height = height * scale_factor
# Create transparent image - RGBA mode allows for transparency
img = Image.new('RGBA', (img_width, img_height), (0, 0, 0, 0))
draw = ImageDraw.Draw(img) # Create drawing object
# Call custom drawing function (passed as a parameter)
# This function will draw the specific style elements
draw_func(draw, img_width, img_height)
# Apply blur for smoothing and resize to target dimensions
# Add slight blur for anti-aliasing
img = img.filter(ImageFilter.GaussianBlur(radius=0.5))
img = img.resize((width, height), Image.LANCZOS) # Resize to target dimensions
# Convert to Tkinter-compatible format
return ImageTk.PhotoImage(img)

def draw(self):
# Abstract method - to be implemented by subclasses
# Each radio button style will override this with its own drawing code
pass



# ========================================================================
# Manages a group of radio buttons ensuring only one is selected at a time
# This implements the classic radio button behavior
# ========================================================================
class RadioGroup:
def __init__(self, command=None):
self.radios = [] # List of radio buttons in this group
self.selected = None # Currently selected radio button
self.command = command # Function to call when selection changes
def add_radio(self, radio):
# Add a radio button to this group
self.radios.append(radio)
def select(self, radio):
# Select a radio button in this group
# If it's different from the currently selected one
if self.selected != radio:
# Deselect previous selection if any
if self.selected is not None:
self.selected.deselect()
# Update selection and notify
self.selected = radio
radio.select()
# Call group command if provided
if self.command:
self.command(radio.value)




# ========================================================================
# Neon style radio button with a glowing effect
# ========================================================================
class NeonRadioButton(RadioButton):
def draw(self):
self.delete("all") # Clear the canvas before redrawing
# Define colors for this style
bg_off_color = "#333333" # Background color when off (dark gray)
bg_on_color = "#00FF88" # Background color when on (bright green)
# Apply hover effect - brighten slightly when hovered
hover_boost = 0.2 if self.hover else 0.0
# Calculate current state based on animation and hover
# This combines hover and selection state for smooth transitions
current_progress = min(1.0, self.animation_progress + hover_boost)
# Get color between off and on colors based on current progress
current_bg_color = self.interpolate_color(bg_off_color, bg_on_color,
current_progress)
# Calculate positions for drawing
center_x = self.width / 2
center_y = self.height / 2
outer_radius = min(center_x, center_y) - 2 # Slightly smaller than canvas
# Draw main circle - the base of the radio button
self.create_circle(center_x, center_y, outer_radius,
fill=current_bg_color, outline="")
# Draw inner dot when selected - appears as animation progresses
if self.animation_progress > 0:
dot_color = "#FFFFFF" # White dot
# Dot size grows with animation progress
dot_radius = outer_radius * 0.6 * self.animation_progress
self.create_circle(center_x, center_y, dot_radius,
fill=dot_color, outline="")
# Draw glow effect when selected - creates the "neon" look
if self.animation_progress > 0:
glow_color = "#00FF88" # Green glow
# Glow width increases with animation progress
glow_width = int(3 * self.animation_progress)
if glow_width > 0:
self.create_circle(center_x, center_y, outer_radius,
fill="", outline=glow_color, width=glow_width)




# ========================================================================
# Gradient style radio button with color transitions
# ========================================================================
class GradientRadioButton(RadioButton):
def draw(self):
self.delete("all") # Clear the canvas before redrawing
# Define colors for gradient
unchecked_start_color = (255, 107, 107) # Red start (RGB values)
unchecked_end_color = (254, 202, 87) # Yellow end (RGB values)
checked_start_color = (72, 52, 212) # Purple start (RGB values)
checked_end_color = (104, 109, 224) # Blue end (RGB values)
# Apply hover effect - brighten slightly when hovered
hover_boost = 0.1 if self.hover else 0.0
effective_progress = min(1.0, self.animation_progress + hover_boost)
# Calculate current gradient colors based on state
# This interpolates between unchecked and checked colors
# For the start color of the gradient:
start_r = int(unchecked_start_color[0] * (1 - effective_progress) +
checked_start_color[0] * effective_progress)
start_g = int(unchecked_start_color[1] * (1 - effective_progress) +
checked_start_color[1] * effective_progress)
start_b = int(unchecked_start_color[2] * (1 - effective_progress) +
checked_start_color[2] * effective_progress)
# For the end color of the gradient:
end_r = int(unchecked_end_color[0] * (1 - effective_progress) +
checked_end_color[0] * effective_progress)
end_g = int(unchecked_end_color[1] * (1 - effective_progress) +
checked_end_color[1] * effective_progress)
end_b = int(unchecked_end_color[2] * (1 - effective_progress) +
checked_end_color[2] * effective_progress)
# Function to draw gradient circle - this is passed to create_smooth_image
def draw_gradient_circle(draw, width, height):
center_x = width / 2
center_y = height / 2
radius = min(center_x, center_y)
# Draw concentric circles with color gradient
# This creates a radial gradient effect
for r in range(int(radius)):
ratio = r / radius # Position in gradient (0 to 1)
# Calculate color at this position in the gradient
r_color = int(start_r * (1 - ratio) + end_r * ratio)
g_color = int(start_g * (1 - ratio) + end_g * ratio)
b_color = int(start_b * (1 - ratio) + end_b * ratio)
color = (r_color, g_color, b_color, 255) # RGBA color
# Draw a circle outline at this radius with calculated color
draw.ellipse([center_x - r, center_y - r,
center_x + r, center_y + r],
outline=color)
# Create gradient image and add to canvas
gradient_img = self.create_smooth_image(self.width, self.height,
draw_gradient_circle)
# Keep reference to prevent garbage collection
self._gradient_img = gradient_img
self.create_image(self.width//2, self.height//2, image=gradient_img)
# Draw inner dot when selected
if self.animation_progress > 0:
center_x = self.width / 2
center_y = self.height / 2
# Dot size increases with animation progress
dot_radius = min(center_x, center_y) * 0.4 * self.animation_progress
# Draw white inner dot
self.create_circle(center_x, center_y, dot_radius,
fill="#FFFFFF", outline="")



# ========================================================================
# Minimal style radio button with simple design
# ========================================================================
class MinimalRadioButton(RadioButton):
def draw(self):
self.delete("all") # Clear the canvas before redrawing
# Define colors for this style
outline_off_color = "#AAAAAA" # Gray outline when off
outline_on_color = "#00FF88" # Green outline when on
# Apply hover effect - brighten slightly when hovered
hover_boost = 0.2 if self.hover else 0.0
effective_progress = min(1.0, self.animation_progress + hover_boost)
# Calculate current outline color based on state
current_outline_color = self.interpolate_color(
outline_off_color, outline_on_color, effective_progress)
# Calculate positions for drawing
center_x = self.width / 2
center_y = self.height / 2
outer_radius = min(center_x, center_y) - 2 # Slightly smaller than canvas
# Calculate outline width based on state - gets thicker when selected
outline_width = 1 + int(2 * effective_progress)
# Draw circle outline - just the border, not filled
self.create_circle(center_x, center_y, outer_radius,
fill="", outline=current_outline_color, width=outline_width)
# Draw inner dot when selected
if self.animation_progress > 0:
# Dot color transitions from gray to green
dot_color = self.interpolate_color(
"#AAAAAA", "#00FF88", self.animation_progress)

# Dot size increases with animation progress
dot_radius = outer_radius * 0.5 * self.animation_progress
# Draw the inner dot
self.create_circle(center_x, center_y, dot_radius,
fill=dot_color, outline="")



# ========================================================================
# Methods for angle calculations (used by CyberpunkRadioButton)
# These convert between degrees and the radians that math functions use
# ========================================================================
def cos_deg(angle):
import math
return math.cos(math.radians(angle))

def sin_deg(angle):
import math
return math.sin(math.radians(angle))


# ========================================================================
# Cyberpunk style radio button with tech-inspired design
# ========================================================================
class CyberpunkRadioButton(RadioButton):
def draw(self):
self.delete("all") # Clear the canvas before redrawing

# Calculate positions for drawing
center_x = self.width / 2
center_y = self.height / 2
outer_radius = min(center_x, center_y) - 2 # Slightly smaller than canvas
# Draw dark metallic background - base of the button
self.create_circle(center_x, center_y, outer_radius,
fill="#151820", outline="")
# Cyberpunk color scheme - neon magenta and cyan
unchecked_color = "#FF00FF" # Magenta
checked_color = "#00FFFF" # Cyan
# Apply hover effect - brighten slightly when hovered
hover_boost = 0.2 if self.hover else 0.0
effective_progress = min(1.0, self.animation_progress + hover_boost)
# Calculate current border color based on state
border_color = self.interpolate_color(
unchecked_color, checked_color, effective_progress)
# Add hexagon pattern to simulate tech/circuit pattern
num_segments = 6 # Number of segments in the hexagon
segment_angle = 360 / num_segments # Angle of each segment
segment_radius = outer_radius * 0.85 # Size of hexagon
# Draw hexagon segments - creates a tech/circuit looking pattern
for i in range(num_segments):
angle1 = i * segment_angle # Start angle of segment
angle2 = (i + 1) * segment_angle # End angle of segment
# Calculate points for segment using trigonometry
x1 = center_x + segment_radius * 0.98 * cos_deg(angle1)
y1 = center_y + segment_radius * 0.98 * sin_deg(angle1)
x2 = center_x + segment_radius * cos_deg(angle2)
y2 = center_y + segment_radius * sin_deg(angle2)
# Create hexagon segment - alternate segments are colored
if i % 2 == 0: # Only color even-numbered segments
seg_color = self.interpolate_color("#151820", border_color,
0.3 * effective_progress)
self.create_line(center_x, center_y, x1, y1, x2, y2,
fill=seg_color, width=1, smooth=True)
# Add techno border with animated width - gets thicker when selected
border_width = 1.5 + int(effective_progress * 2.5)
self.create_circle(center_x, center_y, outer_radius,
fill="", outline=border_color, width=border_width)
# Add inner tech effect when selected/animated
if self.animation_progress > 0:
inner_radius = outer_radius * 0.6
# Function to draw cyberpunk center with power button symbol
def draw_cyber_center(draw, width, height):
center_x = width / 2
center_y = height / 2
radius = min(center_x, center_y) * 0.9
# Draw active element with pulse effect - opacity based on animation
pulse_opacity = int(255 * self.animation_progress)
# Draw circular power button symbol - the outer ring
ring_radius = radius * 0.8
draw.ellipse([center_x - ring_radius, center_y - ring_radius,
center_x + ring_radius, center_y + ring_radius],
outline=(0, 255, 255, pulse_opacity),
width=int(width * 0.08))

# Draw power symbol line - the vertical line in power symbol
line_length = ring_radius * 0.6
line_width = int(width * 0.12)
draw.line([center_x, center_y - line_length * 0.5,
center_x, center_y + line_length * 0.5],
fill=(255, 0, 255, pulse_opacity),
width=line_width)

# Add HUD elements - small accents around the button
# These are small rectangles at the top, right, bottom, left
for i in range(4):
angle = i * 90 # 0, 90, 180, 270 degrees
hud_size = radius * 0.3
# Calculate position using trigonometry
x = center_x + (radius - hud_size/2) * cos_deg(angle)
y = center_y + (radius - hud_size/2) * sin_deg(angle)
# Small tech accent elements
draw.rectangle([x - hud_size/2, y - hud_size/8,
x + hud_size/2, y + hud_size/8],
fill=(0, 255, 255, pulse_opacity//3),
outline=(0, 255, 255, pulse_opacity))
# Create center image with power button and add to canvas
center_img = self.create_smooth_image(int(inner_radius*2),
int(inner_radius*2), draw_cyber_center)
# Keep reference to prevent garbage collection
self._center_img = center_img
self.create_image(center_x, center_y, image=center_img)
# Add external circuit elements when hovered or selected
# These are lines radiating outward from the button
if self.hover or self.animation_progress > 0:
circuit_color = self.interpolate_color(
unchecked_color, checked_color, effective_progress)
# Create multiple circuit lines radiating outward at 45° angles
for angle in [45, 135, 225, 315]:
line_length = outer_radius * 0.4
# Start point on the circle
x1 = center_x + outer_radius * cos_deg(angle)
y1 = center_y + outer_radius * sin_deg(angle)
# End point extends outward
x2 = center_x + (outer_radius + line_length) * cos_deg(angle)
y2 = center_y + (outer_radius + line_length) * sin_deg(angle)
# Draw circuit line
self.create_line(x1, y1, x2, y2, fill=circuit_color, width=1)
# Add circuit node (small circle) at end of line
node_size = 2 + self.animation_progress * 2
self.create_circle(x2, y2, node_size, fill=circuit_color, outline="")




# ========================================================================
# Neumorphic style radio button - soft UI with shadow effects
# ========================================================================
class NeumorphicRadioButton(RadioButton):
def __init__(self, parent, width=36, height=36, group=None,
value=None, command=None):
# Call the parent class constructor with our parameters
# The parent RadioButton class handles the basic functionality
super().__init__(parent, width=width, height=height,
group=group, value=value, command=command)
# Define the color scheme for our neumorphic effect
# These colors create the 3D shadow effect that makes the button look raised
self.base_color = "#262626" # Main button color (dark gray)
self.light_shadow = "#3A3A3A" # Light shadow for the 3D effect (lighter gray)
self.dark_shadow = "#121212" # Dark shadow for the 3D effect (darker gray)
self.accent_color = "#00A3FF" # Blue color shown when the button is selected
def draw(self):
"""
Draw the radio button with neumorphic effects.
This method is called whenever the button needs to be redrawn
(initialization, state changes, etc.)
"""
# Clear any existing drawings on the canvas
self.delete("all")
# Calculate the center point of our button
center_x = self.width / 2
center_y = self.height / 2
# Define the outer radius
# (slightly smaller than max possible for better spacing)
outer_radius = min(center_x, center_y) - 3
# Calculate visual effects based on button state
# These values will be used to adjust shadows and colors

# Effect when button is selected
pressed_effect = 0.3 if self.is_selected else 0
# Effect when mouse hovers over button
hover_effect = 0.15 if self.hover else 0
# Use the stronger of the two effects
combined_effect = max(pressed_effect, hover_effect)
# This inner function will be passed to create_smooth_image
# to draw the main button
def draw_neumorphic_circle(draw, width, height):
"""
Draw a neumorphic circle with proper shadows.
The 'draw' parameter is a PIL drawing context.
"""
# Calculate center and radius for this drawing context
center_x = width / 2
center_y = height / 2
# Slightly smaller for better appearance
radius = min(center_x, center_y) * 0.95
# Set the base color, making it slightly darker when pressed/hovered
base_color_rgb = (38, 38, 38) # Default RGB color
if combined_effect > 0:
# Darken the color slightly based on pressed/hover state
base_color_rgb = (int(38 - 5 * combined_effect),
int(38 - 5 * combined_effect),
int(38 - 5 * combined_effect))

# Draw the main circle with the base color
# Parameters are [left, top, right, bottom] coordinates of bounding box
draw.ellipse([center_x - radius, center_y - radius,
center_x + radius, center_y + radius],
fill=base_color_rgb + (255,)) # Add alpha channel (fully opaque)

# Define shadow properties
shadow_width = int(radius * 0.25) # How wide the shadows should be
shadow_layers = 12 # More layers = smoother gradient

# Create multiple shadow layers with decreasing opacity for a smooth effect
for i in range(shadow_layers):
# Calculate progress through the shadow layers (0.0 to 1.0)
progress = i / shadow_layers
# Shadow strength decreases when button is pressed
shadow_strength = 1.0 - (combined_effect * 0.7)
# Calculate radius for this shadow layer
r = radius - progress * radius * 0.08
# Calculate opacity for this layer (fades out as we move outward)
opacity = int(200 * (1 - progress) * shadow_strength)
# Calculate shadow width (thinner as we move outward)
shadow_width = max(1, int(3 * (1 - progress)))
# Draw dark shadow in top-left quadrant (135° to 315°)
# This simulates light coming from bottom-right
draw.arc([center_x - r, center_y - r,
center_x + r, center_y + r],
135, 315, fill=(18, 18, 18, opacity), width=shadow_width)

# Draw light shadow in bottom-right quadrant (-45° to 135°)
# This completes the 3D effect
draw.arc([center_x - r, center_y - r,
center_x + r, center_y + r],
-45, 135, fill=(58, 58, 58, opacity), width=shadow_width)

# Add a subtle highlight along the edge for extra depth
edge_r = radius * 0.97
edge_opacity = int(120 * (1 - combined_effect * 0.5))
draw.arc([center_x - edge_r, center_y - edge_r,
center_x + edge_r, center_y + edge_r],
-30, 150, fill=(75, 75, 75, edge_opacity), width=2)
# Create the main button image using our drawing function
# create_smooth_image handles anti-aliasing for smooth edges
circle_img = self.create_smooth_image(self.width, self.height,
draw_neumorphic_circle)
self._circle_img = circle_img # Store reference to prevent garbage collection
self.create_image(center_x, center_y, image=circle_img) # Add image to canvas
# Calculate size for inner effect (shadows inside the button)
inner_effect_size = outer_radius * 0.7
# This function draws the inner shadows and highlights
def draw_inner_effect(draw, width, height):
"""
Draw inner shadows and highlights based on button state.
Different effects for selected vs hovered states.
"""
center_x = width / 2
center_y = height / 2
radius = min(center_x, center_y) * 0.9
# Different effects based on whether the button is selected or just hovered
if self.is_selected:
# For selected state: create a recessed circular area effect
# Calculate opacity for shadows based on animation progress
# animation_progress gradually increases when selection changes
shadow_opacity = int(180 * self.animation_progress)
highlight_opacity = int(140 * self.animation_progress)
# Draw inner circle with darker base color to create impression of depth
inner_color = (int(38 - 12 * self.animation_progress),
int(38 - 10 * self.animation_progress),
int(38 - 8 * self.animation_progress),
int(255 * self.animation_progress))
draw.ellipse([center_x - radius, center_y - radius,
center_x + radius, center_y + radius],
fill=inner_color)
# Calculate radius for inner highlights
inner_r = radius * 0.92
# Draw bottom-right inner highlight
draw.arc([center_x - inner_r, center_y - inner_r,
center_x + inner_r, center_y + inner_r],
-45, 135, fill=(50, 50, 50, highlight_opacity), width=2)
# Draw top-left inner shadow
draw.arc([center_x - inner_r, center_y - inner_r,
center_x + inner_r, center_y + inner_r],
135, 315, fill=(15, 15, 15, shadow_opacity), width=2)
elif self.hover:
# For hover state: create a subtle glow effect
glow_opacity = int(180)
# Create a subtle radial gradient
# by drawing progressively smaller circles
for i in range(8):
progress = i / 8
r = radius * (1 - progress * 0.2)
opacity = int(glow_opacity * (1 - progress))
# Draw outline circle with decreasing opacity
draw.ellipse([center_x - r, center_y - r,
center_x + r, center_y + r],
outline=(200, 200, 200, opacity), width=1)
# Create inner effect image if the button is selected or hovered
if self.is_selected or self.hover:
inner_img = self.create_smooth_image(
int(inner_effect_size * 2), # Width
int(inner_effect_size * 2), # Height
draw_inner_effect
)
self._inner_img = inner_img # Store reference to prevent garbage collection
self.create_image(center_x, center_y, image=inner_img) # Add to canvas
# Draw the indicator dot when selected, with a nice glow effect
if self.animation_progress > 0:
def draw_indicator(draw, width, height):
"""
Draw the center indicator dot with a glow effect.
This shows the button is selected.
"""
center_x = width / 2
center_y = height / 2
# Extract RGB components from accent color (#00A3FF)
r, g, b = 0, 163, 255
# Calculate dot size based on animation progress
dot_radius = width * 0.25 * self.animation_progress
opacity = int(255 * self.animation_progress)
# Draw the central indicator dot
draw.ellipse([center_x - dot_radius, center_y - dot_radius,
center_x + dot_radius, center_y + dot_radius],
fill=(r, g, b, opacity))
# Add a glow effect around the dot using concentric circles
for i in range(20):
glow_progress = i / 20
# Each circle gets progressively larger
glow_radius = dot_radius * (1 + glow_progress * 0.8)
# Each circle gets progressively more transparent
glow_opacity = int(150*(1 - glow_progress)*self.animation_progress)

# Draw glow circle (outline only)
draw.ellipse([center_x - glow_radius, center_y - glow_radius,
center_x + glow_radius, center_y + glow_radius],
outline=(r, g, b, glow_opacity), width=1)
# Create indicator with glow effect
indicator_size = outer_radius * 0.8
indicator_img = self.create_smooth_image(
int(indicator_size * 2), # Width
int(indicator_size * 2), # Height
draw_indicator
)
self._indicator_img = indicator_img # Store reference
self.create_image(center_x, center_y, image=indicator_img) # Add to canvas






# Main application that showcases all radio button styles
class ModernRadioButtonsApp(tk.Tk):
def __init__(self):
super().__init__()
# Setup main window
self.title("Radio Button Collection")
self.geometry("600x700")
self.configure(bg="#1A1A1A")
# Create main frame
main_frame = tk.Frame(self, bg="#1A1A1A", padx=15, pady=15)
main_frame.pack(fill=tk.BOTH, expand=True)
# Add title
title_label = tk.Label(main_frame, text="Custom Radio Button Styles",
fg="#FFFFFF", bg="#1A1A1A", font=("Segoe UI", 24))
title_label.pack(pady=(0, 20))

# Add each radio button style with its own group
self.create_radio_group(main_frame, "Neon Style", NeonRadioButton)
self.create_spacer(main_frame, 15)

self.create_radio_group(main_frame, "Gradient Style", GradientRadioButton)
self.create_spacer(main_frame, 15)
self.create_radio_group(main_frame, "Minimal Style", MinimalRadioButton)
self.create_spacer(main_frame, 15)
self.create_radio_group(main_frame, "Cyberpunk Style", CyberpunkRadioButton)
self.create_spacer(main_frame, 15)
self.create_radio_group(main_frame, "Neumorphic Style", NeumorphicRadioButton)


# Add status label to show selection
self.status_label = tk.Label(main_frame, text="No selection",
fg="#FFFFFF", bg="#1A1A1A",
font=("Segoe UI", 16))
self.status_label.pack(pady=10)


def create_radio_group(self, parent, label_text, radio_class):
# Create a frame for the radio group and label
group_frame = tk.Frame(parent, bg="#1A1A1A", pady=10)
group_frame.pack(fill=tk.X)
# Add group label
label = tk.Label(group_frame, text=label_text,
fg="#FFFFFF", bg="#1A1A1A",
font=("Segoe UI", 16))
label.pack(anchor=tk.W, pady=(0, 10))
# Create frame for radio buttons
radio_frame = tk.Frame(group_frame, bg="#1A1A1A")
radio_frame.pack(fill=tk.X)
# Create radio group with callback
radio_group = RadioGroup(command=self.update_status)
# Add radio buttons to the group
for i in range(3):
option_frame = tk.Frame(radio_frame, bg="#1A1A1A")
option_frame.pack(side=tk.LEFT, padx=20)
# Create radio button
radio = radio_class(option_frame, group=radio_group, value=f"Option {i+1}")
radio.pack(side=tk.LEFT)
# Add option label
option_label = tk.Label(option_frame, text=f"Option {i+1}",
fg="#FFFFFF", bg="#1A1A1A",
font=("Segoe UI", 12))
option_label.pack(side=tk.LEFT, padx=10)


def create_spacer(self, parent, height):
# Create a vertical spacer with specified height
spacer = tk.Frame(parent, bg="#1A1A1A", height=height)
spacer.pack(fill=tk.X)


def update_status(self, value):
# Update status label with currently selected value
self.status_label.config(text=f"Selected: {value}")




# Run the application
if __name__ == "__main__":
app = ModernRadioButtonsApp()
app.mainloop()



The Final Result:

Python Tkinter Custom Radio Button Styles


Custom Radio Button Styles In Python Tkinter

5 Custom Radio Buttons With Different Styles In Python Tkinter



if you want the source code click on the download button below