Scrollbar in JScrollPane does not work on JTables

I have a JScrollPane with number of huge JTables in it.

image

While i'm scrolling down the JScrollPane by mouse scroll, it just stops when the mouse pointer passes a JTable. (i.e. Scrollbar works only on B area but not in A.)

How can I avoid this? Thanks.

Here is the code:

/*
 * test.java
 *
 * Created on Jun 26, 2011, 7:39:43 PM
 */
package collector;

import javax.swing.JScrollPane;

/**
 *
 * @author Bhathiya
 */
public class test extends javax.swing.JFrame {

    /** Creates new form test */
    public test() {
        initComponents();
        jScrollPane2.setWheelScrollingEnabled( false );
        jScrollPane3.setWheelScrollingEnabled( false );
    }

    /** This method is called from within the constructor to
     * initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is
     * always regenerated by the Form Editor.
     */
    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">
    private void initComponents() {

        jScrollPane1 = new javax.swing.JScrollPane();
        jPanel1 = new javax.swing.JPanel();
        jScrollPane2 = new javax.swing.JScrollPane();
        jTable1 = new javax.swing.JTable();
        jScrollPane3 = new javax.swing.JScrollPane();
        jTable2 = new javax.swing.JTable();

        setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);

        jScrollPane1.setHorizontalScrollBarPolicy(javax.swing.ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);

        jScrollPane2.setHorizontalScrollBarPolicy(javax.swing.ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
        jScrollPane2.setVerticalScrollBarPolicy(javax.swing.ScrollPaneConstants.VERTICAL_SCROLLBAR_NEVER);

        jTable1.setModel(new javax.swing.table.DefaultTableModel(
            new Object [][] {
                {null, null, null, null},
                {null, null, null, null},
                {null, null, null, null},
                {null, null, null, null},
                {null, null, null, null},
                {null, null, null, null},
                {null, null, null, null},
                {null, null, null, null},
                {null, null, null, null},
                {null, null, null, null},
                {null, null, null, null},
                {null, null, null, null},
                {null, null, null, null},
                {null, null, null, null},
                {null, null, null, null}
            },
            new String [] {
                "Title 1", "Title 2", "Title 3", "Title 4"
            }
        ));
        jTable1.setAutoscrolls(false);
        jScrollPane2.setViewportView(jTable1);

        jScrollPane3.setHorizontalScrollBarPolicy(javax.swing.ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
        jScrollPane3.setVerticalScrollBarPolicy(javax.swing.ScrollPaneConstants.VERTICAL_SCROLLBAR_NEVER);

        jTable2.setModel(new javax.swing.table.DefaultTableModel(
            new Object [][] {
                {null, null, null, null},
                {null, null, null, null},
                {null, null, null, null},
                {null, null, null, null},
                {null, null, null, null},
                {null, null, null, null},
                {null, null, null, null},
                {null, null, null, null},
                {null, null, null, null},
                {null, null, null, null},
                {null, null, null, null},
                {null, null, null, null},
                {null, null, null, null},
                {null, null, null, null},
                {null, null, null, null},
                {null, null, null, null},
                {null, null, null, null},
                {null, null, null, null},
                {null, null, null, null},
                {null, null, null, null}
            },
            new String [] {
                "Title 1", "Title 2", "Title 3", "Title 4"
            }
        ));
        jTable2.setAutoscrolls(false);
        jTable2.setCursor(new java.awt.Cursor(java.awt.Cursor.DEFAULT_CURSOR));
        jScrollPane3.setViewportView(jTable2);

        javax.swing.GroupLayout jPanel1Layout = new javax.swing.GroupLayout(jPanel1);
        jPanel1.setLayout(jPanel1Layout);
        jPanel1Layout.setHorizontalGroup(
            jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(jPanel1Layout.createSequentialGroup()
                .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
                    .addComponent(jScrollPane3, javax.swing.GroupLayout.Alignment.LEADING, 0, 0, Short.MAX_VALUE)
                    .addComponent(jScrollPane2, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.PREFERRED_SIZE, 374, javax.swing.GroupLayout.PREFERRED_SIZE))
                .addContainerGap(151, Short.MAX_VALUE))
        );
        jPanel1Layout.setVerticalGroup(
            jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(jPanel1Layout.createSequentialGroup()
                .addComponent(jScrollPane2, javax.swing.GroupLayout.PREFERRED_SIZE, 298, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 131, Short.MAX_VALUE)
                .addComponent(jScrollPane3, javax.swing.GroupLayout.PREFERRED_SIZE, 168, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addGap(194, 194, 194))
        );

        jScrollPane1.setViewportView(jPanel1);

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
        getContentPane().setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 544, Short.MAX_VALUE)
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 300, Short.MAX_VALUE)
        );

        pack();
    }// </editor-fold>

    /**
     * @param args the command line arguments
     */
    public static void main(String args[]) {

        java.awt.EventQueue.invokeLater(new Runnable() {

            public void run() {
                new test().setVisible(true);
            }
        });
    }
    // Variables declaration - do not modify
    private javax.swing.JPanel jPanel1;
    private javax.swing.JScrollPane jScrollPane1;
    private javax.swing.JScrollPane jScrollPane2;
    private javax.swing.JScrollPane jScrollPane3;
    private javax.swing.JTable jTable1;
    private javax.swing.JTable jTable2;
    // End of variables declaration
}

It's probably caused by the fact that that each table has its own JScrollPane (that's at least the case of your table C). When the mouse is inside a table, the inner-most scroll pane is the one that reacts to the mouse wheel. I don't think you should modify that: it's normal behaviour.

EDITED :

It's ugly, but I'm not sure there is another way of doing it. I've been able to make your example work by removing the listener added to the scroll pane by its UI (even if wheel scrolling is disabled) :

for (MouseWheelListener listener : jScrollPane2.getMouseWheelListeners()) {
    jScrollPane2.removeMouseWheelListener(listener);
}
// same for jScrollPane3

It's not elegant, but having a several scrollable tables inside a scrollabl panel isn't either.


I have a JScrollPane with number of huge JTables in it.

I assume each of the child tables are also added to a JScrollPane. If so then the scroll event is being passed to these scroll panes and not the out scroll pane. So you need to use:

scrollPane.setWheelScrollingEnabled( false );

on each of the scrollpanes contained within the main scrollpane.

Update:

The problem is that even though the scroll wheel has been disable, the scrollpane intercepts all the mouseScrolled events and they don't get passed to the parent scrollpane. So the solution is to not add the table to a scrollpane. Instead use a JPanel with a BorderLayout. Something like:

import java.awt.*;
import java.util.*;
import javax.swing.*;
import javax.swing.table.*;

public class TableMultiple extends JPanel
{
    public TableMultiple()
    {
        setLayout( new BorderLayout() );
        Box box = Box.createVerticalBox();
        box.add(Box.createVerticalStrut(50));

        JPanel panel = new JPanel( new BorderLayout() );
        JTable table = new JTable(10, 5);
        panel.add(table.getTableHeader(), BorderLayout.NORTH);
        panel.add(table);
        box.add( panel );

        box.add(Box.createVerticalStrut(50));

        JTable table2 = new JTable(100, 5);
        table2.setPreferredScrollableViewportSize(table.getPreferredSize());
        JScrollPane scrollPane2 = new JScrollPane( table2 );
        box.add( scrollPane2 );

        box.add(Box.createVerticalStrut(50));

        JTable table3 = new JTable(10, 5);
        box.add( table3 );

        box.add(Box.createVerticalStrut(50));

        add( new JScrollPane(box) );
    }

    private static void createAndShowUI()
    {
        JFrame frame = new JFrame("TableMultiple");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.add( new TableMultiple() );
        frame.setSize(400, 500);
        frame.setLocationRelativeTo( null );
        frame.setVisible( true );
    }

    public static void main(String[] args)
    {
        EventQueue.invokeLater(new Runnable()
        {
            public void run()
            {
                createAndShowUI();
            }
        });
    }
}