javaswingjscrollpanejscrollbar

Change the background slowly while scrolling


I'm trying to create a small program, that I want to change the background slowly while scrolling the scrollbar (JScrollPane). It's like onscroll function in Javascript.

I created the scroll pane and added to it a frame then put some components in it, what I want now, is when the user scrolls, the BG of the scroll pane changes slowly from black to white, when it reaches the bounds of the frame:

This how I created the frame and scroll pane:

public AdminFrame() {
    setBounds(20, 20, 1300, 700);
    setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    getContentPane().setLayout(new BorderLayout(0, 0));
    
    JPanel contentPane = new JPanel();
    contentPane.setForeground(Color.WHITE);
    contentPane.setFont(new Font("Tahoma", Font.BOLD, 11));
    contentPane.setBounds(120, 50, 692, 7);
    contentPane.setPreferredSize(new Dimension(1300, 1500));
    getContentPane().add(contentPane, BorderLayout.CENTER);
    contentPane.setLayout(null);
    JScrollPane scrollPane=new JScrollPane(contentPane,JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED,JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
    scrollPane.setBackground(BgColor);
    scrollPane.getVerticalScrollBar().setUnitIncrement(25);
}

I tested many ideas, also many block of solutions that I found in the web but nothing works.

Like:

scrollPane.getViewport().addChangeListener(new ChangeListener() {
            
    @Override
    public void stateChanged(ChangeEvent e) {
        // TODO Auto-generated method stub
        contentPane.setBackground(Color.white);
        System.out.println("scorled");
        
    }
} )

Or:

scrollPane.getVerticalScrollBar().addAdjustmentListener(new AdjustmentListener() {
            
    @Override
    public void adjustmentValueChanged(AdjustmentEvent e) {
        // TODO Auto-generated method stub
          scrollPane.setBackground(new Color(BgColor.getRed()-10,BgColor.getBlue()-10,BgColor.getGreen()-10)); //change the background color;
    }
});

Solution

  • Introduction

    Your "simple" project is not simple in Java. Java is not the same language as JavaScript. Simple things in JavaScript can be incredibly hard to duplicate in Java.

    Here's a GUI I put together. This is the initial state.

    Color Change 1

    This is the state with the vertical scroll bar about halfway down.

    Color Change 2

    This is the state with the vertical scroll bar all the way down.

    Color Change 3

    Explanation

    Oracle has a nifty tutorial, Creating a GUI With JFC/Swing that will take you through the many many steps to create a Swing GUI. Skip the Netbeans section.

    I created a background JPanel. I placed the background JPanel inside a JScrollPane. I placed the JScrollPane inside the main JPanel. I placed the main JPanel inside a JFrame.

    I started the Swing application with a call to the SwingUtilities invokeLater method. This method ensures that the Swing components will be created and executed on the Event Dispatch Thread.

    I used Swing layout managers to layout the Swing components.

    Code

    Here's the complete runnable code. I made all the classes inner classes so I could post the code as one block.

    import java.awt.BorderLayout;
    import java.awt.Color;
    import java.awt.Dimension;
    import java.awt.event.AdjustmentEvent;
    import java.awt.event.AdjustmentListener;
    
    import javax.swing.BorderFactory;
    import javax.swing.JFrame;
    import javax.swing.JPanel;
    import javax.swing.JScrollBar;
    import javax.swing.JScrollPane;
    import javax.swing.SwingUtilities;
    
    public class BackgroundColorChangeGUI implements Runnable {
    
        public static void main(String[] args) {
            SwingUtilities.invokeLater(new BackgroundColorChangeGUI());
        }
        
        private final BackgroundColorChangeModel model;
        
        private BackgroundPanel backgroundPanel;
        
        public BackgroundColorChangeGUI() {
            this.model = new BackgroundColorChangeModel();
        }
    
        @Override
        public void run() {
            JFrame frame = new JFrame("Color Change");
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            
            frame.add(createMainPanel(), BorderLayout.CENTER);
            
            frame.pack();
            frame.setLocationByPlatform(true);
            frame.setVisible(true);
        }
        
        private JPanel createMainPanel() {
            JPanel panel = new JPanel(new BorderLayout());
            panel.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
            
            backgroundPanel = new BackgroundPanel();
            Dimension d = backgroundPanel.getPreferredSize();
            int displayHeight = 400;
            panel.setPreferredSize(new Dimension(d.width + 50, displayHeight));
            
            JScrollPane scrollPane = new JScrollPane(backgroundPanel);
            
            JScrollBar scrollBar = scrollPane.getVerticalScrollBar();
            scrollBar.setMaximum(d.height - displayHeight + 13);
            scrollBar.setUnitIncrement(1);
            model.setMinimumValue(scrollBar.getMinimum());
            model.setMaximumValue(scrollBar.getMaximum());
            scrollBar.addAdjustmentListener(new ScrollListener());
            
            panel.add(scrollPane);
            
            return panel;
        }
        
        public class BackgroundPanel extends JPanel {
    
            private static final long serialVersionUID = 1L;
            
            public BackgroundPanel() {
                this.setPreferredSize(new Dimension(300, 5000));
                setBackgroundColor(Color.BLACK);
            }
    
            public void setBackgroundColor(Color backgroundColor) {
                this.setBackground(backgroundColor);
            }
            
        }
        
        public class ScrollListener implements AdjustmentListener {
    
            @Override
            public void adjustmentValueChanged(AdjustmentEvent event) {
    //          System.out.println(event.getValue());
                Color color = createBackgroundColor(event.getValue());
                backgroundPanel.setBackgroundColor(color);
            }
            
            private Color createBackgroundColor(int value) {
                // Black is 0, 0, 0; white is 255, 255, 255
                int range = model.getMaximumValue() - model.getMinimumValue();
                int colorValue = value * 255 / range;
                return new Color(colorValue, colorValue, colorValue);
            }
            
        }
        
        public class BackgroundColorChangeModel {
            
            private int minimumValue;
            private int maximumValue;
            
            public int getMinimumValue() {
                return minimumValue;
            }
            
            public void setMinimumValue(int minimumValue) {
                this.minimumValue = minimumValue;
            }
            
            public int getMaximumValue() {
                return maximumValue;
            }
            
            public void setMaximumValue(int maximumValue) {
                this.maximumValue = maximumValue;
            }
            
        }
    
    }