Affichage des articles dont le libellé est java Hamburger Menu. Afficher tous les articles
Affichage des articles dont le libellé est java Hamburger Menu. Afficher tous les articles

Java Swing Hamburger Menu

How to Create a Hamburger Menu in Java Netbeans




In this Java Tutorial we will see How To Create a modern hamburger menu navigation with smooth animations and custom icons In Java Using Netbeans.


What We'll Build?
    An animated hamburger menu that slides in from the left.
    - Custom drawn icons for each menu item.
    - Transitions and hover effects.
    - A responsive overlay system.


What We Are Gonna Use In This Project:

- Java Programming Language.
- NetBeans Editor.





Project Source Code:



/**
 *
 * @author 1BestCsharp
 */
public class HamburgerMenu extends JFrame {
    // Menu state and animation properties
    private boolean isMenuOpen = false;    // Tracks if menu is currently open
    private JPanel sideMenu;               // The side navigation panel
    private Timer animationTimer;          // Controls the animation speed
    private float currentWidth = 0;        // Current width during animation
    private float currentAlpha = 0;        // Current transparency of overlay
    
    // Constants for menu appearance and animation
    private final int MENU_WIDTH = 280;            // Width of the side menu
    private final int ANIMATION_DURATION = 250;    // Total animation time in milliseconds
    private final int ANIMATION_STEPS = 30;        // Number of steps in animation
    
    // UI Components
    private HamburgerIcon hamburgerIcon;   // The hamburger/close button
    private JPanel overlay;                // Semi-transparent overlay behind menu
    
    // Colors used throughout the UI
    private final Color accentColor = new Color(75, 107, 251);        // Highlight color
    private final Color backgroundColor = new Color(245, 245, 250);    // Main background
    private final Color menuBackground = new Color(25, 25, 35);       // Menu background
    private final Color menuHoverColor = new Color(45, 45, 55);       // Menu item hover color
    private final Color menuActiveColor = new Color(55, 155, 65);      // Menu item active color
    
    public HamburgerMenu(){
        // Set up the main window
        setTitle("Hamburger Menu");
        setSize(1000, 700);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setLocationRelativeTo(null);  // Center the window on screen
        setBackground(backgroundColor);
        
        // Create the main content area
        JPanel mainContent = new JPanel();
        mainContent.setLayout(new BorderLayout());
        mainContent.setBackground(backgroundColor);
        
        // Create header with hamburger button
        setupHeader();
        
        // Create semi-transparent overlay that appears behind the menu
        setupOverlay();
        
        // Create side menu with navigation options
        setupSideMenu();
        
        
        // Set up layered pane for menu animation
        setupLayeredPane(mainContent);
        
        
        // Set up animation timer that controls the menu slide effect
        setupAnimationTimer();
        
    }
    
    
    /**
     * Sets up the header section with title and hamburger icon
     */
    private void setupHeader() {
        hamburgerIcon = new HamburgerIcon();
        
        // Create header panel with a subtle bottom border
        JPanel headerPanel = new JPanel(new BorderLayout());
        headerPanel.setBackground(Color.WHITE);
        headerPanel.setBorder(BorderFactory.createCompoundBorder(
            BorderFactory.createMatteBorder(0, 0, 1, 0, new Color(230, 230, 235)),
            BorderFactory.createEmptyBorder(15, 15, 15, 15)
        ));
        
        // Add title to header
        JLabel titleLabel = new JLabel("Dashboard");
        titleLabel.setFont(new Font("Segoe UI", Font.BOLD, 20));
        titleLabel.setForeground(new Color(40, 40, 45));
        titleLabel.setBorder(BorderFactory.createEmptyBorder(0, 20, 0, 0));
        
        // Add components to header
        headerPanel.add(hamburgerIcon, BorderLayout.WEST);
        headerPanel.add(titleLabel, BorderLayout.CENTER);
        
        // Add header to main frame
        add(headerPanel, BorderLayout.NORTH);
        
    }
    
    /**
     * Sets up the semi-transparent overlay that appears when menu is open
     */
    private void setupOverlay() {
        // Create transparent panel that darkens when menu opens
        overlay = new JPanel() {
            @Override
            protected void paintComponent(Graphics g) {
                super.paintComponent(g);
                Graphics2D g2d = (Graphics2D) g;
                // Set transparency based on animation progress
                g2d.setColor(new Color(0, 0, 0, (int)(currentAlpha * 120)));
                g2d.fillRect(0, 0, getWidth(), getHeight());
            }
        };
        overlay.setOpaque(false);
        overlay.setBounds(0, 0, 2000, 1200);
        
        // Close menu when clicking overlay
        overlay.addMouseListener(new MouseAdapter() {
            @Override
            public void mouseClicked(MouseEvent e) {
                toggleMenu();
            }
        });
        
        overlay.setVisible(false);
        
    }
    
    
    /**
     * Sets up the side navigation menu with menu items
     */
    private void setupSideMenu() {
        // Create the main menu panel
        sideMenu = new JPanel();
        sideMenu.setLayout(new BoxLayout(sideMenu, BoxLayout.Y_AXIS));
        sideMenu.setBackground(menuBackground);
        
        // Add brand/logo section at the top
        JPanel brandPanel = new JPanel(new FlowLayout(FlowLayout.LEFT, 20, 25));
        brandPanel.setBackground(menuBackground);
        brandPanel.setMaximumSize(new Dimension(MENU_WIDTH, 80));
        
        JLabel brandLabel = new JLabel("Modern UI");
        brandLabel.setFont(new Font("Segoe UI", Font.BOLD, 24));
        brandLabel.setForeground(Color.WHITE);
        brandPanel.add(brandLabel);
        sideMenu.add(brandPanel);
        sideMenu.add(Box.createVerticalStrut(20));  // Add spacing
        
        // Define menu item names
        String[] menuItems = {
            "Dashboard", "Profile", "Analytics", "Settings", "Help", "Logout"
        };
        
        // Create and add each menu item
        for (int i = 0; i < menuItems.length; i++) {
            JPanel menuItemPanel = createMenuItemPanel(menuItems[i], i);
            sideMenu.add(menuItemPanel);
            sideMenu.add(Box.createVerticalStrut(5));  // Add spacing between items
        }
    }
    
    
    
    /**
     * Sets up the layered pane that allows components to overlap
     * This enables the menu to slide over the main content
     */
    private void setupLayeredPane(JPanel mainContent) {
        JLayeredPane layeredPane = new JLayeredPane();
        layeredPane.setLayout(null);
        
        // Position components
        mainContent.setBounds(0, 0, 2000, 1200);
        sideMenu.setBounds(-MENU_WIDTH, 0, MENU_WIDTH, 1200);
        
        // Add components to layers (higher number = in front)
        layeredPane.add(mainContent, JLayeredPane.DEFAULT_LAYER);     // Bottom layer
        layeredPane.add(overlay, JLayeredPane.PALETTE_LAYER);         // Middle layer
        layeredPane.add(sideMenu, JLayeredPane.MODAL_LAYER);          // Top layer
        
        add(layeredPane, BorderLayout.CENTER);
        
    }
    
    
    /**
     * Sets up animation timer that controls the menu sliding effect
     */
    private void setupAnimationTimer() {
        animationTimer = new Timer(ANIMATION_DURATION / ANIMATION_STEPS, e -> {
            if (isMenuOpen) {
                // Opening animation - increase width and opacity
                currentWidth = Math.min(currentWidth + MENU_WIDTH / ANIMATION_STEPS, MENU_WIDTH);
                currentAlpha = Math.min(currentAlpha + 1.0f / ANIMATION_STEPS, 1.0f);
            }  else {
                // Closing animation - decrease width and opacity
                currentWidth = Math.max(currentWidth - MENU_WIDTH / ANIMATION_STEPS, 0);
                currentAlpha = Math.max(currentAlpha - 1.0f / ANIMATION_STEPS, 0.0f);
            }
            
            // Update positions and visibility based on animation progress
            sideMenu.setBounds((int) (-MENU_WIDTH + currentWidth), 0, MENU_WIDTH, 1200);
            overlay.setVisible(currentAlpha > 0);
            hamburgerIcon.setRotation(currentWidth / MENU_WIDTH * 180);
            
            // Stop animation when complete
            if ((isMenuOpen && currentWidth == MENU_WIDTH) || (!isMenuOpen && currentWidth == 0)) {
                animationTimer.stop();
            }
            repaint();
            
        });
        
    }

    /**
     * Toggles the menu open or closed state and starts animation
     */
    private void toggleMenu() {
        isMenuOpen = !isMenuOpen;  // Toggle state
        animationTimer.start();    // Start animation
    }
    
    
    /**
     * Creates a menu item panel with icon and text
     * 
     * @param text The text label for the menu item
     * @param iconType The type of icon to display (0-5)
     * @return A panel containing the menu item
     */
    private JPanel createMenuItemPanel(String text, int iconType) {
        // Create main panel
        JPanel panel = new JPanel();
        panel.setLayout(new BorderLayout());
        panel.setMaximumSize(new Dimension(MENU_WIDTH, 50));
        panel.setBackground(menuBackground);
        panel.setBorder(BorderFactory.createEmptyBorder(8, 20, 8, 20));
        panel.setCursor(new Cursor(Cursor.HAND_CURSOR));
        
        // Create left indicator panel (shows colored bar when active)
        JPanel indicatorPanel = new JPanel();
        indicatorPanel.setPreferredSize(new Dimension(4, 0));
        indicatorPanel.setBackground(menuBackground);
        
        // Create icon
        IconPanel iconPanel = new IconPanel(iconType);
        iconPanel.setPreferredSize(new Dimension(24, 24));
        
        // Create text label
        JLabel textLabel = new JLabel(text);
        textLabel.setFont(new Font("Segoe UI", Font.PLAIN, 15));
        textLabel.setForeground(Color.WHITE);
        textLabel.setBorder(BorderFactory.createEmptyBorder(0, 15, 0, 0));
        
        // Container to hold icon and text
        JPanel contentPanel = new JPanel(new BorderLayout());
        contentPanel.setBackground(menuBackground);
        contentPanel.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 0));
        contentPanel.add(iconPanel, BorderLayout.WEST);
        contentPanel.add(textLabel, BorderLayout.CENTER);
        
        // Add components to main panel
        panel.add(indicatorPanel, BorderLayout.WEST);
        panel.add(contentPanel, BorderLayout.CENTER);
        
        // Add interaction effects (hover, click)
        addMenuItemInteraction(panel, contentPanel, indicatorPanel, text);
        
        return panel;
        
    }
    
    
    /**
     * Adds mouse interaction behavior to menu items
     */
    private void addMenuItemInteraction(JPanel panel, JPanel contentPanel, 
                                       JPanel indicatorPanel, String text) {
        panel.addMouseListener(new MouseAdapter() {
            @Override
            public void mouseEntered(MouseEvent e) {
                // Hover effect - change background color
                panel.setBackground(menuHoverColor);
                contentPanel.setBackground(menuHoverColor);
                indicatorPanel.setBackground(menuHoverColor);
                
                // Show active indicator on hover
                indicatorPanel.removeAll();
                JPanel activeIndicator = new JPanel();
                activeIndicator.setBackground(accentColor);
                indicatorPanel.setLayout(new BorderLayout());
                indicatorPanel.add(activeIndicator);
                panel.revalidate();
                panel.repaint();  
            }
            
            
            @Override
            public void mouseExited(MouseEvent e) {
                // Reset to normal state
                panel.setBackground(menuBackground);
                contentPanel.setBackground(menuBackground);
                indicatorPanel.setBackground(menuBackground);
                
                // Remove active indicator
                indicatorPanel.removeAll();
                panel.revalidate();
                panel.repaint();
                
            }
            
            @Override
            public void mousePressed(MouseEvent e) {
                // Click down effect
                panel.setBackground(menuActiveColor);
                contentPanel.setBackground(menuActiveColor);
                indicatorPanel.setBackground(menuActiveColor);
            }
            
            @Override
            public void mouseReleased(MouseEvent e) {
                // Click up effect
                panel.setBackground(menuHoverColor);
                contentPanel.setBackground(menuHoverColor);
                indicatorPanel.setBackground(menuHoverColor);
            }
            
            @Override
            public void mouseClicked(MouseEvent e) {
                // Handle menu item click
                System.out.println("Menu item clicked: " + text);
            }
            
        });
        
    }
    
    
    /**
     * IconPanel draws custom vector icons for menu items
     */
    private class IconPanel extends JPanel {
        private int iconType;  // Type of icon to draw
        
        public IconPanel(int iconType) {
            this.iconType = iconType;
            setPreferredSize(new Dimension(24, 24));
            setOpaque(false);
        }
        
        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            Graphics2D g2d = (Graphics2D) g;
            // Enable antialiasing for smoother drawing
            g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
            g2d.setColor(Color.WHITE);
            
            int w = getWidth();
            int h = getHeight();
            
            // Draw different icon based on type
            switch (iconType) {
                case 0: // Dashboard
                    drawDashboardIcon(g2d, w, h);
                    break;
                case 1: // Profile
                    drawProfileIcon(g2d, w, h);
                    break;
                case 2: // Analytics
                    drawAnalyticsIcon(g2d, w, h);
                    break;
                case 3: // Settings
                    drawSettingsIcon(g2d, w, h);
                    break;
                case 4: // Help
                    drawHelpIcon(g2d, w, h);
                    break;
                case 5: // Logout
                    drawLogoutIcon(g2d, w, h);
                    break;
            }
            
        }
        
        /**
         * Draws dashboard icon (four squares in a grid)
         */
        private void drawDashboardIcon(Graphics2D g2d, int w, int h) {
            int padding = 3;
            int size = Math.min(w, h) - (2 * padding);
            int x = (w - size) / 2;
            int y = (h - size) / 2;
            
            int gridSize = size / 2 - 1;
            
            // Draw 4 squares to represent dashboard
            g2d.fillRect(x, y, gridSize, gridSize);
            g2d.fillRect(x + gridSize + 2, y, gridSize, gridSize);
            g2d.fillRect(x, y + gridSize + 2, gridSize, gridSize);
            g2d.fillRect(x + gridSize + 2, y + gridSize + 2, gridSize, gridSize);
            
        }
        
        /**
         * Draws profile icon (person silhouette)
         */
        private void drawProfileIcon(Graphics2D g2d, int w, int h) {
            int padding = 3;
            int size = Math.min(w, h) - (2 * padding);
            int x = (w - size) / 2;
            int y = (h - size) / 2;
            
            // Draw head circle
            int headSize = size / 2;
            g2d.fillOval(x + (size - headSize) / 2, y, headSize, headSize);
            
            // Draw body
            int bodyWidth = size / 2;
            int bodyHeight = size / 2;
            int bodyX = x + (size - bodyWidth) / 2;
            int bodyY = y + headSize;
            
            // Create body shape
            Path2D.Float body = new Path2D.Float();
            body.moveTo(bodyX, bodyY);
            body.lineTo(bodyX + bodyWidth, bodyY);
            body.lineTo(bodyX + bodyWidth + (bodyWidth / 2), bodyY + bodyHeight);
            body.lineTo(bodyX - (bodyWidth / 2), bodyY + bodyHeight);
            body.closePath();
            
            g2d.fill(body);
            
        }
        
        /**
         * Draws analytics icon (bar chart)
         */
        private void drawAnalyticsIcon(Graphics2D g2d, int w, int h) {
            int padding = 4;
            int size = Math.min(w, h) - (2 * padding);
            int x = (w - size) / 2;
            int y = (h - size) / 2;
            
            int barWidth = size / 4;
            
            // Draw three bars of increasing height
            g2d.fillRect(x, y + size - (size / 3), barWidth, size / 3);
            g2d.fillRect(x + barWidth * 1 + 1, y + size - (size / 2), barWidth, size / 2);
            g2d.fillRect(x + barWidth * 2 + 2, y + size - (size / 1), barWidth, size);
            
        }
        
        /**
         * Draws settings icon (gear)
         */
        private void drawSettingsIcon(Graphics2D g2d, int w, int h) {
            int centerX = w / 2;
            int centerY = h / 2;
            int outerRadius = w / 2 - 2;  // Outer radius of gear
            int innerRadius = outerRadius - 5;  // Inner radius of gear
            int teethCount = 8;  // Number of teeth on gear
            
            // Draw center circle
            g2d.fillOval(centerX - innerRadius/2, centerY - innerRadius/2, 
                          innerRadius, innerRadius);
            
            // Draw gear teeth
            for (int i = 0; i < teethCount; i++) {
                double angle = Math.toRadians(i * (360.0 / teethCount));
                
                // Create a tooth shape
                Path2D.Float tooth = new Path2D.Float();
                
                // Starting point (inner gear)
                double x1 = centerX + innerRadius * Math.cos(angle - 0.2);
                double y1 = centerY + innerRadius * Math.sin(angle - 0.2);
                tooth.moveTo(x1, y1);
                
                // Outer point
                double x2 = centerX + outerRadius * Math.cos(angle);
                double y2 = centerY + outerRadius * Math.sin(angle);
                tooth.lineTo(x2, y2);
                
                // End point (back to inner gear)
                double x3 = centerX + innerRadius * Math.cos(angle + 0.2);
                double y3 = centerY + innerRadius * Math.sin(angle + 0.2);
                tooth.lineTo(x3, y3);
                
                // Draw the tooth
                g2d.fill(tooth);
            }
            
        }
        
        /**
         * Draws help icon (question mark)
         */
        private void drawHelpIcon(Graphics2D g2d, int w, int h) {
            int padding = 3;
            int size = Math.min(w, h) - (2 * padding);
            int x = (w - size) / 2;
            int y = (h - size) / 2;
            
            // Draw outer circle
            g2d.setStroke(new BasicStroke(2f));
            g2d.drawOval(x, y, size, size);
            
            int centerX = x + size/2;
            int centerY = y + size/2;
            int radius = size/2;
            
            // Draw question mark stem (vertical line at bottom)
            g2d.setStroke(new BasicStroke(2.5f, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND));
            g2d.drawLine(centerX, centerY + radius/3, centerX, centerY + 2*radius/3);
            
            // Draw question mark dot
            //g2d.fillOval(centerX - 1, centerY - radius/3 - 1, 3, 3);
            
            // Draw curved top of question mark
            Path2D.Float curve = new Path2D.Float();
            curve.moveTo(centerX - radius/3, centerY - radius/4);
            curve.quadTo(centerX - radius/3, centerY - radius/2, centerX, centerY - radius/2);
            curve.quadTo(centerX + radius/3, centerY - radius/2, centerX + radius/3, centerY - radius/4);
            curve.quadTo(centerX + radius/3, centerY, centerX, centerY);
            
            g2d.setStroke(new BasicStroke(2.5f, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND));
            g2d.draw(curve);
        }
        
        /**
         * Draws logout icon (door with arrow)
         */
        private void drawLogoutIcon(Graphics2D g2d, int w, int h) {
            int padding = 2;
            int size = Math.min(w, h) - (2 * padding);
            int x = (w - size) / 2;
            int y = (h - size) / 2;
            
            // Set thicker stroke for better visibility
            g2d.setStroke(new BasicStroke(2f, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND));
            
            // Draw door frame
            int doorWidth = (int)(size * 0.6);
            int doorHeight = size;
            g2d.drawRect(x, y, doorWidth, doorHeight);
            
            // Draw door handle
            int handleX = x + doorWidth - 3;
            int handleY = y + doorHeight/2;
            g2d.fillOval(handleX - 3, handleY - 3, 6, 6);
            
            // Draw arrow pointing out
            int arrowStartX = x + doorWidth + 2;
            int arrowEndX = x + size;
            int arrowY = y + doorHeight/2;
            
            // Arrow line
            g2d.drawLine(arrowStartX, arrowY, arrowEndX, arrowY);
            
            // Arrow head
            int arrowHeadSize = 5;
            g2d.drawLine(arrowEndX - arrowHeadSize, arrowY - arrowHeadSize, arrowEndX, arrowY);
            g2d.drawLine(arrowEndX - arrowHeadSize, arrowY + arrowHeadSize, arrowEndX, arrowY);
            
        }
        
    }
    
    
    /**
     * HamburgerIcon class creates the animated hamburger/close button
     */
    private class HamburgerIcon extends JPanel {
        private float rotation = 0;        // Current rotation angle
        private boolean isHovered = false; // Hover state
        
        public HamburgerIcon() {
            setPreferredSize(new Dimension(32, 32));
            setBackground(Color.WHITE);
            setCursor(new Cursor(Cursor.HAND_CURSOR));
            
            // Add mouse interaction
            addMouseListener(new MouseAdapter() {
                @Override
                public void mouseClicked(MouseEvent e) {
                    toggleMenu(); // Toggle menu when clicked
                }
                
                @Override
                public void mouseEntered(MouseEvent e) {
                    isHovered = true;
                    repaint();
                }
               
                @Override
                public void mouseExited(MouseEvent e) {
                    isHovered = false;
                    repaint();
                } 
            });
        }
        
        /**
         * Sets the rotation angle for the icon animation
         * @param rotation Angle in degrees (0 = hamburger, 180 = X)
         */
        public void setRotation(float rotation) {
            this.rotation = rotation;
            repaint();
        }
        
        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            Graphics2D g2d = (Graphics2D) g;
            g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, 
                    RenderingHints.VALUE_ANTIALIAS_ON);
            
            int centerX = getWidth() / 2;
            int centerY = getHeight() / 2;
            
            // Save current transform to restore later
            AffineTransform oldTransform = g2d.getTransform();
            
            // Rotate around center
            g2d.rotate(Math.toRadians(rotation), centerX, centerY);
            
            // Set color based on hover state
            g2d.setColor(isHovered ? new Color(60, 60, 65) : new Color(40, 40, 45));
            g2d.setStroke(new BasicStroke(2.2f, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND));
            
            // Draw either hamburger or X based on rotation
            if (rotation < 90) {
                // Hamburger state (three lines)
                g2d.drawLine(8, 11, 24, 11);
                g2d.drawLine(8, 16, 24, 16);
                g2d.drawLine(8, 21, 24, 21);
            }  else {
                // Close (X) state
                g2d.drawLine(11, 11, 21, 21);
                g2d.drawLine(11, 21, 21, 11);
            }
            
            // Restore original transform
            g2d.setTransform(oldTransform);
            
        }
        
    }
    
    public static void main(String[] args) {
        
         SwingUtilities.invokeLater(() -> {
            try {
                // Use system look and feel for better integration
                UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
            } catch (Exception e) {
                e.printStackTrace();
            }
            
            // Create and show the main window
            HamburgerMenu frame = new HamburgerMenu();
            frame.setVisible(true);
        });
    }

}


  


The Final Result: