Python Banking Project Source Code

How To Create a Banking Application in Python  Tkinter

How To Create a Banking Application in Python  Tkinter


In this Python Tutorial we will see How to Create a simple banking app using Python Tkinter.
In this python tkinter bank project we will create custom panels, buttons and chart, with Real-time balance tracking, Transaction history with visual indicators, Input validation and error handling, Charts showing balance trends .

What We Are Gonna Use In This Project:

- Python Tkinter: Core GUI framework.
- ttkbootstrap: theme system.
- matplotlib: Data visualization for balance history charts.
- NumPy: Numerical operations for chart data.
- Visual Studio Editor.




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




Project Source Code:



     - Build the user interface


def create_widgets(self):
"""
Create and arrange all widgets for the application.
"""
# Main frame to hold all other widgets
main_frame = ttk.Frame(self.root, padding="10 10 10 10")
main_frame.pack(fill=tk.BOTH, expand=True)

# Header frame for logo and date
header_frame = ttk.Frame(main_frame)
header_frame.pack(fill=tk.X, pady=(0, 20))

# Logo
logo_label = ttk.Label(header_frame, text="PyBank",
font=("Roboto", 24, "bold"), foreground=ACCENT_COLOR)
logo_label.pack(side=tk.LEFT)

# Current date display
date_label = ttk.Label(header_frame,
text=datetime.datetime.now().strftime("%B %d, %Y"),
font=("Roboto", 12))
date_label.pack(side=tk.RIGHT)

# Content area to hold balance, input, and chart
content_frame = ttk.Frame(main_frame)
content_frame.pack(fill=tk.BOTH, expand=True)

# Balance display card
balance_frame = ttk.Frame(content_frame, style="Card.TFrame")
balance_frame.grid(row=0, column=0, padx=(0, 10), pady=(0, 10), sticky="nsew")

balance_title = ttk.Label(balance_frame, text="Current Balance",
font=("Roboto", 16, "bold"), foreground=ACCENT_COLOR)
balance_title.pack(pady=(10, 5))

self.balance_label = ttk.Label(balance_frame, text="$0.00",
font=("Roboto", 28, "bold"),
foreground=SECONDARY_ACCENT)
self.balance_label.pack(pady=(0, 10))

# Transaction input frame
input_frame = ttk.Frame(content_frame, style="Card.TFrame")
input_frame.grid(row=1, column=0, padx=(0, 10), pady=(0, 10), sticky="nsew")

amount_label = ttk.Label(input_frame, text="Transaction Amount",
font=("Roboto", 14))
amount_label.pack(pady=(10, 5))

self.amount_entry = ttk.Entry(input_frame, font=("Roboto", 14))
self.amount_entry.pack(pady=(0, 10), padx=10, fill=tk.X)

button_frame = ttk.Frame(input_frame)
button_frame.pack(pady=(0, 10), fill=tk.X)

# Custom styled buttons for deposit and withdraw
deposit_btn = ttb.Button(button_frame, text="Deposit",
bootstyle=(SUCCESS, SOLID),
command=lambda: self.handle_transaction("deposit"))
deposit_btn.pack(side=tk.LEFT, padx=(10, 5), fill=tk.X, expand=True)

withdraw_btn = ttb.Button(button_frame, text="Withdraw",
bootstyle=(DANGER, SOLID),
command=lambda: self.handle_transaction("withdraw"))
withdraw_btn.pack(side=tk.RIGHT, padx=(5, 10), fill=tk.X, expand=True)

# Chart area for balance history
self.chart_frame = ttk.Frame(content_frame, style="Card.TFrame")
self.chart_frame.grid(row=0, column=1, rowspan=2, padx=(10, 0),
pady=(0, 10), sticky="nsew")

chart_title = ttk.Label(self.chart_frame, text="Balance History",
font=("Roboto", 16, "bold"),
foreground=ACCENT_COLOR)
chart_title.pack(pady=(10, 5))

self.create_chart()

# Transaction history frame
history_frame = ttk.Frame(content_frame, style="Card.TFrame")
history_frame.grid(row=2, column=0, columnspan=2, sticky="nsew")

history_title = ttk.Label(history_frame, text="Transaction History",
font=("Roboto", 16, "bold"),
foreground=ACCENT_COLOR)
history_title.pack(pady=(10, 5))

# Frame to hold the Treeview and scrollbar
tree_frame = ttk.Frame(history_frame)
tree_frame.pack(pady=(0, 10), padx=10, fill=tk.BOTH, expand=True)

# Create the Treeview for transaction history
self.history_tree = ttk.Treeview(tree_frame,
columns=("Type", "Amount", "Date"),
show="headings", height=8)
self.history_tree.pack(side=tk.LEFT, fill=tk.BOTH, expand=True)

# Add a vertical scrollbar to the Treeview
scrollbar = ttk.Scrollbar(tree_frame, orient="vertical",
command=self.history_tree.yview)
scrollbar.pack(side=tk.RIGHT, fill=tk.Y)
self.history_tree.configure(yscrollcommand=scrollbar.set)

# Configure Treeview columns
self.history_tree.heading("Type", text="Type")
self.history_tree.heading("Amount", text="Amount")
self.history_tree.heading("Date", text="Date")
self.history_tree.column("Type", width=100)
self.history_tree.column("Amount", width=100)
self.history_tree.column("Date", width=150)

# Apply custom styles to the Treeview
self.style_treeview()

# Configure grid weights for responsive layout
content_frame.grid_columnconfigure(0, weight=1)
content_frame.grid_columnconfigure(1, weight=1)
content_frame.grid_rowconfigure(2, weight=1)

    
    

     - Custom Table Styling.

def style_treeview(self):
"""
Apply custom styles to the Treeview widget.
"""
# Configure a modern style for the Treeview
self.style.configure("Treeview",
background="white",
foreground=TEXT_COLOR,
rowheight=30,
fieldbackground="white")
self.style.map('Treeview', background=[('selected', ACCENT_COLOR)])

# Style the Treeview headings
self.style.configure("Treeview.Heading",
background="#EDF2F7",
foreground=TEXT_COLOR,
relief="flat",
font=("Roboto", 11, "bold"))
self.style.map("Treeview.Heading",
background=[('active', '#E2E8F0')])

# Configure tags for deposit and withdraw rows
self.history_tree.tag_configure('deposit', foreground=POSITIVE_COLOR)
self.history_tree.tag_configure('withdraw', foreground=NEGATIVE_COLOR)

        
    

     - Data Visualization Setup.


def create_chart(self):
"""
Create and initialize the balance history chart.
"""
# Create a chart
fig, self.ax = plt.subplots(figsize=(5, 3), facecolor=BACKGROUND_COLOR)

# Create a FigureCanvasTkAgg object and add it to the chart frame
self.canvas = FigureCanvasTkAgg(fig, master=self.chart_frame)
self.canvas.draw()
self.canvas.get_tk_widget().pack(side=tk.TOP, fill=tk.BOTH, expand=1)

# Set the background color of the axis to match the app's background
self.ax.set_facecolor(BACKGROUND_COLOR)

# Style the x and y axis tick labels
self.ax.tick_params(axis='x', colors=TEXT_COLOR)
self.ax.tick_params(axis='y', colors=TEXT_COLOR)

# Style the chart border
for spine in self.ax.spines.values():
spine.set_color('#E2E8F0')

# Initial update of the chart
self.update_chart()

    


     - Dynamic Chart Updates.


def update_chart(self):
"""
Update the balance history chart with current transaction data.
"""
# Clear the previous plot
self.ax.clear()

# Initialize balances list with starting balance of 0
balances = [0]

# Calculate balance history
if len(self.transactions) > 0:

for transaction in self.transactions:

if transaction.type == "deposit":
balances.append(balances[-1] + transaction.amount)

else:
balances.append(balances[-1] - transaction.amount)

# Create x-axis values (transaction indices)
x = range(len(balances))

# Plot the balance history line
self.ax.plot(x, balances, color=ACCENT_COLOR, linewidth=2,
marker='o', markersize=6)

# Fill the area under the line
gradient = np.linspace(0, 1, len(x))
self.ax.fill_between(x, balances, color="red", alpha=0.2)

# Add labels and title
self.ax.set_xlabel('Transactions', color=TEXT_COLOR)
self.ax.set_ylabel('Balance', color=TEXT_COLOR)
#self.ax.set_title('Balance History', color=ACCENT_COLOR, fontweight='bold')

# Style the grid
self.ax.grid(color='#E2E8F0', linestyle='--', linewidth=0.5, alpha=0.7)

# Remove top and right spines
self.ax.spines['right'].set_visible(False)

# Add subtle shadow to the line
shadow_line, = self.ax.plot(x, balances, color='grey',
linewidth=6, alpha=0.2)
shadow_line.set_zorder(self.ax.get_zorder() - 1)

# Add data labels
for i, balance in enumerate(balances):
self.ax.annotate(f'${balance:.2f}', (i, balance),
textcoords="offset points",
xytext=(0,10), ha='center',
fontsize=8, color=TEXT_COLOR)

# Adjust layout and redraw the canvas
plt.tight_layout()
self.canvas.draw()


    


     - Processes both deposit and withdrawal requests with validation and error handling.


def handle_transaction(self, type):
"""
Process a deposit or withdrawal transaction.
"""
try:
amount = float(self.amount_entry.get())
if amount <= 0:
self.show_error("Please enter a valid positive number")
return

if type == "withdraw" and amount > self.balance:
self.show_error("Insufficient funds")
return

if type == "deposit":
self.balance += amount
self.show_success(f"Successfully deposited ${amount:.2f}")

else:
self.balance -= amount
self.show_success(f"Successfully withdrew ${amount:.2f}")
# Add the new transaction to the list
self.transactions.append(Transaction(type, amount))

# Update UI elements
self.update_balance_label()
self.update_history()
self.update_chart()
self.amount_entry.delete(0, tk.END) # Clear the entry field

except ValueError:
self.show_error("Please enter a valid number")




     - Updates the prominently displayed current balance whenever the account balance changes.


def update_balance_label(self):
"""
Update the displayed balance.
"""
self.balance_label.config(text=f"${self.balance:.2f}")

        


     - Refreshes the transaction history table with the latest transactions.


def update_history(self):
"""
Update the transaction history display.
"""
# Clear existing entries
for i in self.history_tree.get_children():
self.history_tree.delete(i)

# Add transactions to the Treeview
for transaction in reversed(self.transactions):
if transaction.type == "deposit":
icon = "↑" # Up arrow for deposit
tag = 'deposit'
else:
icon = "↓" # Down arrow for withdraw
tag = 'withdraw'

self.history_tree.insert("", "end", values=(
f"{icon} {transaction.type.capitalize()}",
f"${transaction.amount:.2f}",
transaction.date.strftime("%Y-%m-%d %H:%M")
), tags=(tag,))

# Apply alternating row colors
for i, item in enumerate(self.history_tree.get_children()):
if i % 2 == 0:
self.history_tree.item(item,
tags=self.history_tree.item(item, "tags") + ('evenrow',))
else:
self.history_tree.item(item,
tags=self.history_tree.item(item, "tags") + ('oddrow',))
# Configure tag colors
self.history_tree.tag_configure('evenrow', background='#F7FAFC')
self.history_tree.tag_configure('oddrow', background='#EDF2F7')

        


     - Creates and displays custom-styled error dialogs when invalid actions are attempted.


def show_error(self, message):
"""
Display an error message to the user.
"""
# Create custom error dialog instead of using ttkbootstrap's Messagebox
error_dialog = tk.Toplevel(self.root)
error_dialog.title("Error")
error_dialog.geometry("450x170")
error_dialog.configure(bg="white")
error_dialog.resizable(False, False)

# Make dialog modal
error_dialog.transient(self.root)
error_dialog.grab_set()

# Center the dialog on the parent window
x = self.root.winfo_x() + (self.root.winfo_width() / 2) - (450 / 2)
y = self.root.winfo_y() + (self.root.winfo_height() / 2) - (170 / 2)
error_dialog.geometry(f"+{int(x)}+{int(y)}")

# Add error icon and message
frame = ttk.Frame(error_dialog)
frame.pack(fill=tk.BOTH, expand=True, padx=20, pady=20)

error_label = ttk.Label(frame, text="⊘ Error", font=("Arial", 17, "bold"),
foreground=NEGATIVE_COLOR)
error_label.pack(pady=(0, 10))

message_label = ttk.Label(frame, text=message, font=("Arial", 14, ""),
wraplength=400)
message_label.pack(pady=(0, 10))

ok_button = tk.Button(frame, text="OK", bg=ACCENT_COLOR, fg="white", width=10,
command=error_dialog.destroy)
ok_button.pack()

        


     - Shows confirmation dialogs when transactions are successfully completed.


def show_success(self, message):
"""
Display a success message to the user.
"""
# Create custom success dialog
success_dialog = tk.Toplevel(self.root)
success_dialog.title("Success")
success_dialog.geometry("450x170")
success_dialog.configure(bg="white")
success_dialog.resizable(False, False)

# Make dialog modal
success_dialog.transient(self.root)
success_dialog.grab_set()

# Center the dialog on the parent window
x = self.root.winfo_x() + (self.root.winfo_width() / 2) - (450 / 2)
y = self.root.winfo_y() + (self.root.winfo_height() / 2) - (170 / 2)
success_dialog.geometry(f"+{int(x)}+{int(y)}")

# Add success icon and message
frame = ttk.Frame(success_dialog)
frame.pack(fill=tk.BOTH, expand=True, padx=20, pady=20)

success_label = ttk.Label(frame, text="✓ Success", font=("Arial", 17, "bold"),
foreground=SECONDARY_ACCENT)
success_label.pack(pady=(0, 10))

message_label = ttk.Label(frame, text=message, font=("Arial", 14, ""),
wraplength=400)
message_label.pack(pady=(0, 10))

ok_button = tk.Button(frame, text="OK", bg=SECONDARY_ACCENT, fg="white",
width=10, command=success_dialog.destroy)
ok_button.pack()

        




Java Animated Sonic Waves Source Code

How to Create a Sonic Waves animation In Java Netbeans

How to Create a Sonic Waves animation In Java Netbeans


In this Java Tutorial we will see How To Create a Sonic Waves animation that display 7 vertical bars that pulse up and down in a wave pattern with Realistic reflections below the baseline and a  Smooth sine wave animation patterns In Java Swing Using Netbeans.

What We Are Gonna Use In This Project:

- Java Programming Language.
- NetBeans Editor.





Project Source Code:




/**
 *
 * @author 1BestCsharp
 */
public class SonicWaves extends JPanel{

    // Constants that control the appearance of the bars
    private static final int BAR_COUNT = 7;         // Total number of bars to display
    private static final int BAR_WIDTH = 6*2;         // Width of each bar in pixels
    private static final int BAR_GAP = 6*2;           // Space between bars in pixels
    private static final int BAR_HEIGHT = 70*2;       // Maximum height of bars in pixels
    private static final int ANIMATION_DELAY = 1500; // Time in milliseconds for a complete animation cycle
    
    // Array of neon colors used for the bars
    private final Color[] colors = {
            new Color(0, 238, 255),   // neon blue
            new Color(179, 0, 255),   // neon purple
            new Color(255, 0, 255),   // neon pink
            new Color(10, 255, 170)   // neon teal
    };
    
    private final float[] barHeights;  // Stores the current height of each bar (as a fraction from 0.0 to 1.0)
    private final Timer timer;         // Timer that controls the animation
    private int colorIndex = 0;        // Index of the current color in the colors array
    
    public SonicWaves(){
        
        // Set the preferred size for this panel
        setPreferredSize(new Dimension(BAR_COUNT * (BAR_WIDTH + BAR_GAP), BAR_HEIGHT * 2 + 60));
        // Set dark background color
        setBackground(new Color(15, 15, 26));
        
        // Initialize all bars with a small height (0.2 = 20% of maximum height)
        barHeights = new float[BAR_COUNT];
        for (int i = 0; i < BAR_COUNT; i++) {
            barHeights[i] = 0.2f; 
        }
        
        // Create a timer that will update the animation every 40 milliseconds
        timer = new Timer(40, new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
            
                updateBarHeights();  // Calculate new heights for the bars
                repaint();           // Redraw the panel with the new heights
                
            }
        });
        
        // Start the animation timer
        timer.start();
        
    }
    
    
     /**
     * Updates the height of each bar based on a sine wave pattern
     */
    private void updateBarHeights() {
        
        // Get the current system time in milliseconds
        long currentTime = System.currentTimeMillis();
        
        // Calculate new height for each bar
        for(int i = 0; i < BAR_COUNT; i++){
            
            // Calculate a phase offset for each bar to create a wave effect
            double phaseOffset = i * (Math.PI / 8);
            
            // Calculate the current progress through the animation cycle (0.0 to 1.0)
            double progress = (currentTime % ANIMATION_DELAY) / (double) ANIMATION_DELAY;
            
            // Calculate angle for sine wave
            double angle = 2 * Math.PI * progress + phaseOffset;
            
            // Calculate new bar height using sine wave (range from 0.2 to 1.0)
            barHeights[i] = (float) (0.2f + 0.8f * Math.abs(Math.sin(angle)));
            
            // Change colors at the beginning of each animation cycle
            if (currentTime % ANIMATION_DELAY < 50) {
                colorIndex = (colorIndex + 1) % colors.length;
            }
            
        }
        
    }
    
    
    
    
    
     /**
     * This method is called automatically whenever the panel needs to be redrawn
     */
    @Override
    protected void paintComponent(Graphics g){
        
        // Call the parent class's paintComponent method first
        super.paintComponent(g);
        // Create a Graphics2D object for more advanced drawing
        Graphics2D g2d = (Graphics2D) g.create();
        // Enable anti-aliasing for smoother lines and shapes
        g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
                RenderingHints.VALUE_ANTIALIAS_ON);
        
        // Calculate the total width needed for all bars
        int totalWidth = BAR_COUNT * (BAR_WIDTH + BAR_GAP) - BAR_GAP;
        
        // Calculate starting X position to center the bars
        int startX = (getWidth() - totalWidth) / 2;
        // Calculate Y position for the base of the bars
        int baseY = getHeight() / 2 - 20;
        
        // Draw the glowing background
        drawBackgroundGlow(g2d);
        
        // Draw each bar and its reflection
        for(int i = 0; i < BAR_COUNT; i++){
            
            // Calculate the X position for this bar
            int x = startX + i * (BAR_WIDTH + BAR_GAP);
            // Calculate the height for this bar in pixels
            int height = (int) (barHeights[i] * BAR_HEIGHT);
            // Calculate the Y position for the top of the bar
            int y = baseY - height;
            
            // Get a color for this bar (shifts colors between bars)
            Color barColor = colors[(colorIndex + i) % colors.length];
            
            // Draw the main bar
            drawBar(g2d, x, y, height, barColor);
            
             // Draw the reflection of the bar below the baseline
            drawReflection(g2d, x, baseY, height, barColor);
            
        }
        
         // Draw the "Sonic Wave" text label
        drawLabel(g2d, baseY + BAR_HEIGHT + 30);
        
        
        // Clean up the Graphics2D object
        g2d.dispose();
        
    }
    
    
    
     /**
     * Draws a glowing background effect
     */
    private void drawBackgroundGlow(Graphics2D g2d){
        
        // Calculate center of the panel
        int centerX = getWidth() / 2;
        int centerY = getHeight() / 2;
        
        // Calculate radius for the gradient
        int radius = Math.max(getWidth(), getHeight()) / 2;
        
        // Create a radial gradient paint (a gradient that radiates from the center)
        RadialGradientPaint glow = new RadialGradientPaint(
                centerX, centerY, radius,  // Center and radius
                new float[] {0.0f, 0.7f, 1.0f},  // Positions for color stops (0=center, 1=edge)
                new Color[] {  // Colors at each position
                    new Color(30, 30, 50),    // Slightly lighter color at center
                    new Color(20, 20, 35),    // Middle color
                    new Color(15, 15, 26)     // Darker color at edge
                }
        );
        
        // Set the gradient as the current paint
        g2d.setPaint(glow);
        // Fill the entire panel with the gradient
        g2d.fillRect(0, 0, getWidth(), getHeight());
        
    }
    
    
     /**
     * Draws a single bar with glowing effect
     */
    private void drawBar(Graphics2D g2d, int x, int y, int height, Color barColor) {
        
         // Create a gradient for the bar that transitions from white to the bar color
        GradientPaint gradient = new GradientPaint(
                x, y, new Color(255, 255, 255, 220),  // Start with semi-transparent white at top
                x, y + height, barColor);             // End with the bar color at bottom
        
        // Set the gradient as the current paint
        g2d.setPaint(gradient);
        
        // Create a rounded rectangle shape for the bar
        RoundRectangle2D bar = new RoundRectangle2D.Float(x, y, BAR_WIDTH, height, 4, 4);
        // Fill the shape with the gradient
        g2d.fill(bar);
        
        // Save the original composite (transparency) setting
        Composite originalComposite = g2d.getComposite();
        
        // Draw several layers of outlines to create a glow effect
        for(int j = 1; j <= 5; j++){
            
            // Calculate decreasing alpha (transparency) for each outer layer
            float alpha = 0.5f - (j * 0.08f);
            
            // Set the transparency level
            g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, alpha));
            
            // Set the color for the glow
            g2d.setColor(barColor);
            
            // Draw a slightly larger outline around the bar
            g2d.draw(new RoundRectangle2D.Float(x - j, y - j, BAR_WIDTH + 2*j, height + 2*j, 4, 4));
            
        }
        
        // Restore the original composite setting
        g2d.setComposite(originalComposite);
        
    }
    
    
    
     /**
     * Draws the reflection of a bar below the baseline
     */
    private void drawReflection(Graphics2D g2d, int x, int baseY, int height, Color barColor) {
        
        // Save the original composite (transparency) setting
        Composite originalComposite = g2d.getComposite();
        
        // Draw the reflection one line at a time with decreasing opacity
        for(int i = 0; i < height; i++){
            
            // Calculate decreasing opacity as we move down the reflection
            float alphaFactor = 0.4f * (1.0f - ((float)i / height));
            
            // Set the transparency level
            g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, alphaFactor));
            
            // Create a slightly darker color for the reflection
            Color reflectionColor = new Color(
                Math.max(barColor.getRed() - 20, 0),     // Reduce red component (minimum 0)
                Math.max(barColor.getGreen() - 20, 0),   // Reduce green component
                Math.max(barColor.getBlue() - 20, 0)     // Reduce blue component
            );
            
            // Calculate the Y position for this line of the reflection
            int reflectionY = baseY + i;
            // Set the color for this line
            g2d.setColor(reflectionColor);
            // Draw a single line of the reflection
            g2d.fillRoundRect(x, reflectionY, BAR_WIDTH, 1, 2, 2);          
            
        }
        
        // Add a subtle shimmering effect that changes over time
        // Calculate sine wave based on current time for shimmering effect
        float rippleEffect = (float)(Math.sin(System.currentTimeMillis() / 200.0) * 0.1 + 0.2);
        // Set transparency for the shimmer
        g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, rippleEffect));
        // Set a very light color for the shimmer
        g2d.setColor(new Color(255, 255, 255, 40));
        // Draw a semi-transparent overlay on top of the reflection
        g2d.fillRoundRect(x, baseY, BAR_WIDTH, height / 2, 2, 2);
        
        // Restore the original composite setting
        g2d.setComposite(originalComposite);
        
    }
    
    
     /**
     * Draws the "SONIC WAVE" text label
     */
    private void drawLabel(Graphics2D g2d, int y) {
        
        // Text to display
        String label = "SONIC WAVE";
        
        // Set font for the text
        g2d.setFont(new Font("Verdana", Font.BOLD, 24));
        
        // Get font metrics to measure text width
        FontMetrics fm = g2d.getFontMetrics();
        int textWidth = fm.stringWidth(label);
        
        // Calculate X position to center text
        int textX = (getWidth() - textWidth) / 2;
        
        // Draw glowing effect behind text using current color theme
        g2d.setColor(new Color(colors[colorIndex].getRed(), 
                              colors[colorIndex].getGreen(), 
                              colors[colorIndex].getBlue(), 40));  // Semi-transparent
        
        // Draw multiple offset copies of the text to create a glow
        for (int i = 1; i <= 5; i++) {
            g2d.drawString(label, textX - i/2, y + i/2);  // Offset one direction
            g2d.drawString(label, textX + i/2, y - i/2);  // Offset other direction
        }
        
        // Draw the main text in white
        g2d.setColor(new Color(255, 255, 255, 220));
        g2d.drawString(label, textX, y);
        
        // Set up parameters for decorative lines
        int lineLength = 40;  // Length of each line
        int lineY = y + 8;    // Y position (slightly below text)
        int gap = 10;         // Gap between text and lines
        
        // Set color and line thickness for the decorative lines
        g2d.setColor(colors[colorIndex]);
        g2d.setStroke(new BasicStroke(1.5f));
        
        // Draw line to the left of the text
        g2d.drawLine(textX - gap - lineLength, lineY, textX - gap, lineY);
        
        // Draw line to the right of the text
        g2d.drawLine(textX + textWidth + gap, lineY, textX + textWidth + gap + lineLength, lineY);
        
    }
    
    
    
     /**
     * Stops the animation timer when the component is no longer needed
     */
    public void stopAnimation() {
        if (timer.isRunning()) {
            timer.stop();
        }
    }
    
    
    
    public static void main(String[] args) {
        
        SwingUtilities.invokeLater(() -> {
        
             // Create a frame window
            JFrame frame = new JFrame("Sonic Wave Spinner");
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            
             // Create a dark panel to hold the spinner
            JPanel darkPanel = new JPanel(new BorderLayout());
            darkPanel.setBackground(new Color(15, 15, 26));
            darkPanel.setBorder(BorderFactory.createEmptyBorder(20, 20, 20, 20));
            
            // Create and add the waves component
            SonicWaves waves = new SonicWaves();
            darkPanel.add(waves, BorderLayout.CENTER);
            
            // Add the panel to the frame and display it
            frame.getContentPane().add(darkPanel);
            frame.pack();
            frame.setSize(600, 500);
            frame.setLocationRelativeTo(null);  // Center on screen
            frame.setVisible(true);
            
        });
        
    }
    
}
  


The Final Result:

Java Animated Sonic Waves Source Code

Java Animated Sonic Waves

Java Sonic Waves Animation Source Code