Interactive Charts in Java Swing

How to Create Interactive Charts with Animation Effects in Java Netbeans

How to Create Interactive Charts with Animation Effects in Java Netbeans


In this Java Tutorial we will see How To Create an interactive chart application using Java Swing that can display your data as bar charts, line charts, or scatter plots with animations and hover effects In Java Using Netbeans.

FEATURES: 
- Three chart types: Bar, Line, and Scatter 
- Smooth transition animations 
- Interactive hover tooltips 
- Modern dark theme design 
- Professional gradient effects - Responsive layout

What We Are Gonna Use In This Project:

- Java Programming Language.
- NetBeans Editor.





Project Source Code:



/**
 *
 * @author 1BestCsharp
 */

/**
 * Interactive Chart Application
 * This class creates a window displaying an interactive chart that can switch between
 * bar chart, line chart, and scatter plot visualizations.
 */
public class InteractiveChart extends JFrame {
    // The panel that contains the actual chart visualization
    private ChartPanel chartPanel;
    
    // The panel containing buttons to switch between chart types
    private JPanel controlPanel;
    
    // Buttons for selecting different chart types
    private JButton barButton;
    private JButton lineButton;
    private JButton scatterButton;
    
    
    public InteractiveChart(){
        // Set up the window title and behavior
        setTitle("Interactive Chart");
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); // Makes the application close when the X button is clicked
        setLayout(new BorderLayout()); // Use BorderLayout to position components
        
        // Create sample data for the chart
        List<DataPoint> data = new ArrayList<>();
        data.add(new DataPoint("A", 30, "alpha"));
        data.add(new DataPoint("B", 50, "beta"));
        data.add(new DataPoint("C", 80, "gamma"));
        data.add(new DataPoint("D", 40, "delta"));
        data.add(new DataPoint("E", 60, "epsilon"));
        
        // Create the chart panel with our data and add it to the center of the window
        chartPanel = new ChartPanel(data);
        add(chartPanel, BorderLayout.CENTER);
        
        
        // Create the control panel with chart type buttons and add it to the bottom of the window
        createControlPanel();
        add(controlPanel, BorderLayout.SOUTH);
        
        // Set window size and center it on the screen
        setSize(650, 500);
        setLocationRelativeTo(null); // Centers the window on the screen
        
    }
    
    
    /**
     * Creates the bottom panel with buttons for selecting chart types
     */
    private void createControlPanel() {
        // Create a panel with a dark background
        controlPanel = new JPanel();
        controlPanel.setBackground(new Color(24, 28, 43)); // Set dark blue background color
        controlPanel.setBorder(BorderFactory.createEmptyBorder(15, 15, 15, 15)); // Add padding
        controlPanel.setLayout(new FlowLayout(FlowLayout.CENTER, 15, 0)); // Center buttons with spacing
        
        // Create the three chart type buttons
        barButton = createButton("Bar Chart");
        lineButton = createButton("Line Chart");
        scatterButton = createButton("Scatter Plot");
        
        // Set the bar button as active by default
        setActiveButton(barButton);
        
        // Add action listeners to each button to change the chart type when clicked
        barButton.addActionListener(e -> {
            chartPanel.setChartType(ChartType.BAR); // Change chart to bar type
            setActiveButton(barButton); // Update button appearances
        });
        
        lineButton.addActionListener(e -> {
            chartPanel.setChartType(ChartType.LINE); // Change chart to line type
            setActiveButton(lineButton); // Update button appearances
        });
        
        scatterButton.addActionListener(e -> {
           chartPanel.setChartType(ChartType.SCATTER); // Change chart to scatter type
           setActiveButton(scatterButton); // Update button appearances
        });
        
        // Add buttons to the control panel
        controlPanel.add(barButton);
        controlPanel.add(lineButton);
        controlPanel.add(scatterButton);
    }
    
    
    /**
     * Creates a styled button with consistent appearance
     * @param text The text to display on the button
     * @return A configured JButton instance
     */
    private JButton createButton(String text) {
        JButton button = new JButton(text);
        
        // Set button font and appearance
        button.setFont(new Font("Segoe UI", Font.BOLD, 13));
        button.setCursor(new Cursor(Cursor.HAND_CURSOR)); // Changes cursor to hand when hovering
        button.setFocusPainted(false); // Removes the focus outline
        
        // Set button colors
        button.setBackground(new Color(38, 41, 56)); // Dark background
        button.setForeground(new Color(200, 205, 225)); // Light text color
        
        // Create borders with padding
        button.setBorder(BorderFactory.createCompoundBorder(
            BorderFactory.createLineBorder(new Color(48, 51, 66), 1), // Border
            BorderFactory.createEmptyBorder(8, 16, 8, 16) // Padding inside button
        ));
        
        // Add hover effect using mouse listeners
        button.addMouseListener(new MouseAdapter() {
            // When mouse enters (hovers over) the button
            @Override
            public void mouseEntered(MouseEvent e) {
                // Only change color if it's not the active button
                if (button.getForeground().getRGB() != new Color(255, 158, 100).getRGB()) {
                    button.setBackground(new Color(48, 151, 66)); // Lighter green background on hover
                }
            }
            
            // When mouse exits the button
            @Override
            public void mouseExited(MouseEvent e) {
                // Only change color if it's not the active button
                if (button.getForeground().getRGB() != new Color(255, 158, 100).getRGB()) {
                    button.setBackground(new Color(38, 41, 56)); // Return to normal background
                }
            }
        });
        
        return button;
    }
    
    
    /**
     * Updates the appearance of buttons to show which chart type is currently active
     * @param activeButton The button to set as active
     */
    private void setActiveButton(JButton activeButton) {
        // Define colors for inactive buttons
        Color inactiveBackground = new Color(38, 41, 56);
        Color inactiveForeground = new Color(200, 205, 225);
        Color inactiveBorder = new Color(48, 51, 66);
        
        // Reset all buttons to inactive state
        for (JButton button : new JButton[]{barButton, lineButton, scatterButton}) {
            button.setBackground(inactiveBackground);
            button.setForeground(inactiveForeground);
            button.setBorder(BorderFactory.createCompoundBorder(
                BorderFactory.createLineBorder(inactiveBorder, 1),
                BorderFactory.createEmptyBorder(8, 16, 8, 16)
            ));
        }
        
        // Set the active button's style with orange highlight
        activeButton.setBackground(new Color(30, 33, 45));
        activeButton.setForeground(new Color(255, 158, 100)); // Orange text
        activeButton.setBorder(BorderFactory.createCompoundBorder(
            BorderFactory.createLineBorder(new Color(255, 158, 100), 2), // Orange border
            BorderFactory.createEmptyBorder(7, 15, 7, 15)
        ));
        
    }
    
    
    
    public static void main(String[] args) {
       try {
            UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
        } catch (Exception e) {
            e.printStackTrace();
        }
       
        SwingUtilities.invokeLater(() -> {
            InteractiveChart chart = new InteractiveChart();
            chart.setVisible(true); // Make the window visible
        });
    }
    
       
    /**
     * Enum defining the available chart types
     */
    enum ChartType {
        BAR, LINE, SCATTER
    }
    
    /**
     * Class representing a single data point on the chart
     */
    static class DataPoint {
        String label;    // The label shown on the x-axis
        int value;       // The numeric value represented by this point
        String category; // A category grouping for this data point
        
        // Constructor to initialize the data point
        public DataPoint(String label, int value, String category) {
            this.label = label;
            this.value = value;
            this.category = category;
        }
        
    }
    
    
    /**
     * Custom tooltip panel that appears when hovering over data points
     */
    class ChartTooltip extends JPanel {
        
        private String label;
        private String category;
        private int value;
        
        /**
         * Creates a tooltip with data point information
         */
        public ChartTooltip(String label, String category, int value) {
            this.label = label;
            this.category = category;
            this.value = value;
            
            // Style the tooltip
            setBackground(new Color(36, 40, 59)); // Dark background
            setBorder(BorderFactory.createCompoundBorder(
                BorderFactory.createLineBorder(new Color(255, 158, 100), 2, false), // Orange border
                BorderFactory.createEmptyBorder(8, 12, 8, 12) // Padding
            ));
            
        }
        
        /**
         * Custom painting of the tooltip content
         * This method is automatically called when the tooltip needs to be drawn
         */
        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            Graphics2D g2 = (Graphics2D) g; // Cast to Graphics2D for more advanced drawing
            g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); // Smooth edges
            
            // Draw the label and category with light gray color
            g2.setColor(new Color(207, 201, 194));
            g2.setFont(new Font("Segoe UI", Font.BOLD, 14));
            g2.drawString(label + " (" + category + ")", 10, 20);
            
            // Draw the value with orange color
            g2.setColor(new Color(255, 158, 100));
            g2.setFont(new Font("Segoe UI", Font.BOLD, 18));
            g2.drawString(String.valueOf(value), 10, 45);
            
        }
        
        /**
         * Define the preferred size of the tooltip
         */
        @Override
        public Dimension getPreferredSize() {
            return new Dimension(120, 60);
        }
        
    }
    
    
    /**
     * The main chart visualization panel
     * This is where the actual chart drawing happens
     */
    class ChartPanel extends JPanel {
        
        private List<DataPoint> data;            // The data to display
        private ChartType chartType = ChartType.BAR; // The current chart type
        private ChartTooltip tooltip;            // Tooltip to show on hover
        
        // Animation properties
        private Timer animationTimer;            // Timer that controls animation speed
        private float animationProgress = 0;     // Current animation progress (0.0 to 1.0)
        private float animationIncrement = 0.05f; // How much to increase progress each step
        
        // Chart dimensions and margins
        private int leftMargin = 60;    // Space on the left for y-axis labels
        private int rightMargin = 40;   // Space on the right 
        private int topMargin = 40;     // Space at the top for title
        private int bottomMargin = 60;  // Space at the bottom for x-axis labels
        
        // Interactive elements
        private int hoverIndex = -1;    // Index of data point being hovered (-1 means none)
        
        /**
         * Creates a chart panel with the given data
         */
        public ChartPanel(List<DataPoint> data) {
            this.data = data;
            setBackground(new Color(26, 27, 38)); // Dark background
            setBorder(BorderFactory.createEmptyBorder(20, 20, 20, 20)); // Add padding
            
            
            // Create tooltip (initially invisible)
            tooltip = new ChartTooltip("", "", 0);
            tooltip.setVisible(false);
            setLayout(null); // Use absolute positioning for tooltip
            add(tooltip);
            
            
            // Add mouse listeners for interaction
            // This detects when the mouse moves over the chart
            addMouseMotionListener(new MouseMotionAdapter() {
                @Override
                public void mouseMoved(MouseEvent e) {
                    checkHover(e.getX(), e.getY()); // Check if mouse is over a data point
                }
            });
            
            // This detects when the mouse exits the chart area
            addMouseListener(new MouseAdapter() {
                @Override
                public void mouseExited(MouseEvent e) {
                    hoverIndex = -1; // No point is being hovered
                    tooltip.setVisible(false); // Hide tooltip
                    repaint(); // Redraw the chart
                }
            });
            
            // Start with animation
            startAnimation();

        }
        
        
        /**
         * Changes the chart type and restarts the animation
         */
        public void setChartType(ChartType chartType) {
            this.chartType = chartType;
            animationProgress = 0; // Reset animation
            startAnimation(); // Start new animation
        }
        
        /**
         * Starts the animation for chart transitions
         */
        private void startAnimation() {
            // Stop existing animation if running
            if (animationTimer != null && animationTimer.isRunning()) {
                animationTimer.stop();
            }
            
            // Reset and start new animation
            animationProgress = 0;
            
            // Create a timer that fires multiple times to create animation
            animationTimer = new Timer(20, e -> { // Fire every 20 milliseconds
                animationProgress += animationIncrement; // Increase progress
                if (animationProgress >= 1) {
                    animationProgress = 1; // Cap at 100%
                    animationTimer.stop(); // Stop animation
                }
                repaint(); // Redraw the chart with new progress
            });
            
            animationTimer.start(); // Start the timer
            
        }
        
        
        /**
         * Checks if the mouse is hovering over a data point
         * Updates the tooltip position and visibility
         */
        private void checkHover(int mouseX, int mouseY) {
            int chartWidth = getWidth() - leftMargin - rightMargin;
            int chartHeight = getHeight() - topMargin - bottomMargin;
            int barWidth = chartWidth / data.size();
            
            hoverIndex = -1; // Start with no hover
            
            // Check each data point to see if mouse is over it
            for (int i = 0; i < data.size(); i++) {
                DataPoint point = data.get(i);
                int x = leftMargin + i * barWidth + barWidth / 2;
                int y = topMargin + chartHeight - (int)(chartHeight * point.value / 100.0);
                
                // Different hit testing based on chart type
                if (chartType == ChartType.BAR) {
                    // For bar charts, check if mouse is inside the bar rectangle
                    Rectangle barRect = new Rectangle(
                        leftMargin + i * barWidth + 5, 
                        y,
                        barWidth - 10, 
                        chartHeight - (chartHeight - (int)(chartHeight * point.value / 100.0))
                    );
                    if (barRect.contains(mouseX, mouseY)) {
                        hoverIndex = i;
                        break;
                    }
                    
                } else{
                    // For line and scatter, check distance to point
                    double distance = Math.sqrt(Math.pow(mouseX - x, 2) + Math.pow(mouseY - y, 2));
                    if (distance < 15) { // Within 15 pixels
                        hoverIndex = i;
                        break;
                    }
                }
                
                
            }
            
            
            // Update tooltip if hovering over a data point
            if (hoverIndex != -1) {
                DataPoint point = data.get(hoverIndex);
                tooltip.label = point.label;
                tooltip.category = point.category;
                tooltip.value = point.value;
                
                int x = leftMargin + hoverIndex * barWidth + barWidth / 2;
                int y = topMargin + getHeight() - topMargin - bottomMargin - 
                        (int)((getHeight() - topMargin - bottomMargin) * point.value / 100.0);
                
                // Position tooltip above the data point
                tooltip.setBounds(x - 60, y - 70, 120, 60);
                tooltip.setVisible(true);
                
            } else {
                tooltip.setVisible(false); // Hide tooltip if not hovering over a point
            }

            repaint(); // Redraw to show highlighting
            
        }
        
        
        /**
         * Main method to paint the chart components
         * This is called automatically whenever the chart needs to be redrawn
         */
        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            Graphics2D g2 = (Graphics2D) g; // Cast to Graphics2D for more advanced drawing
            g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); // Smooth edges
            
            int width = getWidth();
            int height = getHeight();
            int chartWidth = width - leftMargin - rightMargin;
            int chartHeight = height - topMargin - bottomMargin;
            
            // Draw title
            g2.setColor(new Color(207, 201, 194)); // Light gray color
            g2.setFont(new Font("Segoe UI", Font.BOLD, 20));
            String title = "Performance Metrics";
            int titleWidth = g2.getFontMetrics().stringWidth(title);
            g2.drawString(title, (width - titleWidth) / 2, 30); // Center the title
            
            // Draw title underline
            g2.setColor(new Color(255, 158, 100)); // Orange color
            g2.fillRect((width - 40) / 2, 35, 40, 3);
            
            // Draw axes
            g2.setColor(new Color(169, 177, 214, 60)); // Semi-transparent blue-gray
            g2.drawLine(leftMargin, topMargin, leftMargin, height - bottomMargin); // Y-axis
            g2.drawLine(leftMargin, height - bottomMargin, width - rightMargin, height - bottomMargin); // X-axis
            
            // Draw grid lines and y-axis labels
            g2.setStroke(new BasicStroke(1, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER, 
                                         10, new float[]{5, 5}, 0)); // Dashed line
            
            // Draw 5 horizontal grid lines and labels
            for (int i = 0; i <= 5; i++) {
                int y = topMargin + (chartHeight * i) / 5;
                g2.drawLine(leftMargin, y, width - rightMargin, y); // Grid line
                
                // Y-axis label
                g2.setColor(new Color(169, 177, 214));
                g2.setFont(new Font("Segoe UI", Font.PLAIN, 12));
                String label = String.valueOf(100 - i * 20); // 100, 80, 60, 40, 20, 0
                g2.drawString(label, leftMargin - 30, y + 5);
                g2.setColor(new Color(169, 177, 214, 60)); // Back to transparent for next grid line
                
            }
            
            // Draw x-axis labels (one for each data point)
            g2.setFont(new Font("Segoe UI", Font.PLAIN, 12));
            g2.setColor(new Color(169, 177, 214));
            int barWidth = chartWidth / data.size();
            for (int i = 0; i < data.size(); i++) {
                String label = data.get(i).label;
                int labelWidth = g2.getFontMetrics().stringWidth(label);
                g2.drawString(label, leftMargin + i * barWidth + barWidth / 2 - labelWidth / 2, 
                            height - bottomMargin + 25); // Center under each data point
            }
            
            // Draw the appropriate chart based on current type
            switch (chartType) {
                case BAR:
                    drawBarChart(g2, chartWidth, chartHeight);
                    break;
                case LINE:
                    drawLineChart(g2, chartWidth, chartHeight);
                    break;
                case SCATTER:
                    drawScatterChart(g2, chartWidth, chartHeight);
                    break;
            }
            
        }
        
       
        /**
         * Draws a bar chart visualization
         */
        private void drawBarChart(Graphics2D g2, int chartWidth, int chartHeight) {
            int barWidth = chartWidth / data.size();
            
            // Create gradient paint for bars
            GradientPaint gradient = new GradientPaint(
                0, topMargin, new Color(255, 122, 147), // Pink at top
                0, getHeight() - bottomMargin, new Color(255, 158, 100) // Orange at bottom
            );
            
            // Draw each bar
            for (int i = 0; i < data.size(); i++) {
                DataPoint point = data.get(i);
                
                // Apply animation to bar height
                int barHeight = (int)(chartHeight * point.value / 100.0 * animationProgress);
                int x = leftMargin + i * barWidth + 5;
                int y = getHeight() - bottomMargin - barHeight;
                int width = barWidth - 10;
                
                // Use different color for hovered bar
                if (i == hoverIndex) {
                    g2.setColor(new Color(255, 122, 147)); // Pink when hovered
                } else {
                    g2.setPaint(gradient); // Gradient for normal bars
                }
                
                // Create rounded rectangle for bar
                RoundRectangle2D.Double bar = new RoundRectangle2D.Double(x, y, width, barHeight, 8, 8);
                g2.fill(bar);
                
                // Draw value on top of bar if animation is complete
                if (animationProgress >= 0.95) {
                    g2.setColor(new Color(207, 201, 194)); // Light gray text
                    g2.setFont(new Font("Segoe UI", Font.BOLD, 12));
                    String value = String.valueOf(point.value);
                    int stringWidth = g2.getFontMetrics().stringWidth(value);
                    g2.drawString(value, x + width / 2 - stringWidth / 2, y - 10); // Center above bar
                }
                
            }
            
        } 
        
        
        /**
         * Draws a line chart visualization
         */
        private void drawLineChart(Graphics2D g2, int chartWidth, int chartHeight) {
            int barWidth = chartWidth / data.size();
            
            // Set line properties
            g2.setStroke(new BasicStroke(3, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND)); // Thick line with round caps
            g2.setColor(new Color(255, 158, 100)); // Orange line
            
            // Calculate point coordinates
            int[] xPoints = new int[data.size()];
            int[] yPoints = new int[data.size()];
            
            for (int i = 0; i < data.size(); i++) {
                DataPoint point = data.get(i);
                xPoints[i] = leftMargin + i * barWidth + barWidth / 2;
                
                // Apply animation to y-values
                float valueProgress = point.value * animationProgress;
                yPoints[i] = getHeight() - bottomMargin - (int)(chartHeight * valueProgress / 100.0);
            }
            
            // Create path for the line
            Path2D path = new Path2D.Double();
            path.moveTo(xPoints[0], yPoints[0]); // Start at first point
            
            // Draw smooth line between points using quadratic curves
            for (int i = 1; i < data.size(); i++) {
                // Calculate control point for smooth curve
                double controlX = xPoints[i-1] + (xPoints[i] - xPoints[i-1]) / 2.0;
                
                // First curve: from previous point to midpoint
                path.quadTo(controlX, yPoints[i-1], controlX, yPoints[i-1] + (yPoints[i] - yPoints[i-1]) / 2.0);
                
                // Second curve: from midpoint to current point
                path.quadTo(controlX, yPoints[i], xPoints[i], yPoints[i]);
                
            }
            
            // Draw the path
            g2.draw(path);
            
            // Draw points
            for (int i = 0; i < data.size(); i++) {
                // Only draw points if they've "appeared" in the animation
                if (i <= (data.size() - 1) * animationProgress) {
                    int x = xPoints[i];
                    int y = yPoints[i];
                    
                    // Outer circle (stroke)
                    g2.setColor(new Color(24, 28, 43)); // Dark blue
                    g2.fillOval(x - 7, y - 7, 14, 14);
                    
                    // Inner circle (fill) - different color when hovered
                    if (i == hoverIndex) {
                        g2.setColor(new Color(255, 122, 147)); // Pink when hovered
                    } else {
                        g2.setColor(new Color(255, 158, 100)); // Orange normally
                    }
                    g2.fillOval(x - 5, y - 5, 10, 10);
                    
                    // Draw values if animation complete
                    if (animationProgress >= 0.95) {
                        g2.setColor(new Color(207, 201, 194)); // Light gray text
                        g2.setFont(new Font("Segoe UI", Font.BOLD, 12));
                        String value = String.valueOf(data.get(i).value);
                        int stringWidth = g2.getFontMetrics().stringWidth(value);
                        g2.drawString(value, x - stringWidth / 2, y - 15); // Center above point
                    }

                }
                
            }
 
        }
        

        /**
        * Draws a scatter chart visualization
        */
        private void drawScatterChart(Graphics2D g2, int chartWidth, int chartHeight) {
             int barWidth = chartWidth / data.size();

            // Save the original stroke and composite for later restoration
            Stroke originalStroke = g2.getStroke();
            Composite originalComposite = g2.getComposite();

            // Draw connecting lines to axis - more subtle than before
            g2.setStroke(new BasicStroke(1, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER, 
                                        10, new float[]{3, 3}, 0)); // Finer dashed line
            g2.setColor(new Color(169, 177, 214, 60)); // Very subtle blue-gray

            // Create a drop shadow effect for the points
            for (int i = 0; i < data.size(); i++) {
                // Only draw if this point has "appeared" in the animation
                if (i <= (data.size() - 1) * animationProgress) {
                    DataPoint point = data.get(i);
                    int x = leftMargin + i * barWidth + barWidth / 2;

                    // Apply animation to point position
                    float valueProgress = point.value * animationProgress;
                    int y = getHeight() - bottomMargin - (int)(chartHeight * valueProgress / 100.0);

                    // Draw vertical line to x-axis if animation has progressed
                    if (animationProgress > 0.3) {
                        // Draw line from x-axis to slightly below the point
                        g2.drawLine(x, getHeight() - bottomMargin, x, y + 7);
                    }
                    
                }
                
            }
            
            // Reset stroke for the points
            g2.setStroke(originalStroke);

            // Draw each data point with shadow first, then the actual point
            for (int i = 0; i < data.size(); i++) {
                // Only draw if this point has "appeared" in the animation
                if (i <= (data.size() - 1) * animationProgress) {
                    DataPoint point = data.get(i);
                    int x = leftMargin + i * barWidth + barWidth / 2;

                    // Apply animation to point position
                    float valueProgress = point.value * animationProgress;
                    int y = getHeight() - bottomMargin - (int)(chartHeight * valueProgress / 100.0);

                    // Standard point size - consistent but slightly larger for higher values
                    int pointSize = 14 + (point.value / 20);

                    // Draw shadow first (slightly offset and transparent)
                    g2.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.4f));
                    g2.setColor(new Color(0, 0, 0, 100)); // Transparent black
                    g2.fillOval(x - pointSize/2 + 3, y - pointSize/2 + 3, pointSize, pointSize);

                    // Reset composite for main point drawing
                    g2.setComposite(originalComposite);

                    // Apply a gradient color based on data point value
                    if (i == hoverIndex) {
                        // Special bright highlight color when hovered
                        g2.setColor(new Color(255, 122, 147)); // Bright pink

                        // Draw glow effect for hovered point
                        for (int glow = 3; glow > 0; glow--) {
                            g2.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.1f));
                            g2.fillOval(x - pointSize/2 - glow, y - pointSize/2 - glow, 
                                      pointSize + glow*2, pointSize + glow*2);
                        }
                        g2.setComposite(originalComposite);
                        
                    } else {
                        // Gradient from orange to blue based on value
                        Color pointColor;
                        float hue = 0.1f + (0.6f * point.value / 100.0f); // Range from orange (0.1) to blue (0.7)
                        pointColor = Color.getHSBColor(hue, 0.8f, 0.9f);
                        g2.setColor(pointColor);
                    }
                    
                    // Draw the filled circle
                    g2.fillOval(x - pointSize/2, y - pointSize/2, pointSize, pointSize);

                    // Draw border around circle
                    g2.setColor(new Color(24, 28, 43)); // Dark outline
                    g2.setStroke(new BasicStroke(1.5f));
                    g2.drawOval(x - pointSize/2, y - pointSize/2, pointSize, pointSize);
                    g2.setStroke(originalStroke);

                    // Draw values if animation is complete or nearly complete
                    if (animationProgress >= 0.95) {
                        // Create a small white background for text to improve readability
                        String value = String.valueOf(point.value);
                        g2.setFont(new Font("Segoe UI", Font.BOLD, 12));
                        int stringWidth = g2.getFontMetrics().stringWidth(value);
                        int stringHeight = g2.getFontMetrics().getHeight();

                        // Draw text background
                        g2.setColor(new Color(24, 28, 43, 180)); // Semi-transparent dark background
                        g2.fillRoundRect(x - stringWidth/2 - 4, y - pointSize/2 - stringHeight - 2, 
                                       stringWidth + 8, stringHeight + 2, 6, 6);

                        // Draw value text
                        g2.setColor(new Color(255, 255, 255)); // White text
                        g2.drawString(value, x - stringWidth/2, y - pointSize/2 - 5);
                        
                    }
                    
                }
                
            }

            // Restore original settings
            g2.setStroke(originalStroke);
            g2.setComposite(originalComposite);
  
            
        }
        
        
    }
    
    
}

  


The Final Result:



Bar Chart

Bar Chart Hover

Line Chart

Line Chart Hover

Scatter Chart

Scatter Chart Hover



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




disclaimer: you will get the source code, and to make it work in your machine is your responsibility and to debug any error/exception is your responsibility this project is for the students who want to see an example and read the code not to get and run.






Share this

Related Posts

Latest
Previous
Next Post »