You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何阻止内部JScrollPane消耗鼠标滚轮滚动事件

如何阻止内部JScrollPane消耗鼠标滚轮滚动事件

我正在组装一个包含多个JTable的JPanel——每个JTable都被JScrollPane包裹,这样表头能正常显示;而整个JPanel又套了一层外层的JScrollPane。

我特意把外层JScrollPane的首选尺寸设得比较小,让垂直滚动条显示出来,效果如下:

Example

但现在遇到个问题:用鼠标滚轮滚动的时候,只有鼠标指针在JTable区域外时,外层滚动条才会动。显然是内部的JScrollPane把滚轮事件给吃掉了。

我试过给内部JScrollPane加这行代码:

scrollPane.setWheelScrollingEnabled(false);

但这招不管用,还是没解决问题。

有没有办法让内部的JScrollPane不再消耗鼠标滚轮的滚动事件?

下面是能复现这个问题的最小示例代码:

import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.swing.BorderFactory;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollBar;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.SwingUtilities;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableColumnModel;

public class MultipleJTableExample implements Runnable {

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new MultipleJTableExample());
    }

    @Override
    public void run() {
        JFrame frame = new JFrame("Multiple JTable Example");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        frame.add(createTablePanel(), BorderLayout.CENTER);

        frame.pack();
        frame.setLocationByPlatform(true);
        frame.setVisible(true);
    }

    private JPanel createTablePanel() {
        JPanel outerPanel = new JPanel(new BorderLayout());

        JPanel panel = new JPanel(new GridBagLayout());
        panel.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));

        GridBagConstraints gbc = new GridBagConstraints();
        gbc.anchor = GridBagConstraints.LINE_START;
        gbc.fill = GridBagConstraints.HORIZONTAL;
        gbc.insets = new Insets(0, 0, 20, 0);

        gbc.gridx = 0;
        gbc.gridy = 0;
        Map<String, List<AnimalValue>> animalMap = new AnimalModel()
                .getAnimalMap();
        Set<String> mapSet = animalMap.keySet();
        Iterator<String> iterator = mapSet.iterator();
        while (iterator.hasNext()) {
            String key = iterator.next();
            List<AnimalValue> animalValues = animalMap.get(key);
            panel.add(createSubtablePanel(key, animalValues), gbc);
            gbc.gridy++;
        }

        Dimension d = panel.getPreferredSize();
        int height = d.height / 2;
        int width = d.width + 30;

        JScrollPane scrollPane = new JScrollPane(panel);
        JScrollBar scrollBar = scrollPane.getVerticalScrollBar();
        scrollBar.setMinimum(0);
        scrollBar.setMaximum(d.height);
        scrollBar.setBlockIncrement(32);
        scrollBar.setUnitIncrement(32);
        scrollPane.setPreferredSize(new Dimension(width, height));

        outerPanel.add(scrollPane, BorderLayout.CENTER);

        return outerPanel;
    }

    private JPanel createSubtablePanel(String key,
            List<AnimalValue> animalValues) {
        JPanel panel = new JPanel(new BorderLayout());
        panel.setBorder(BorderFactory.createEmptyBorder(0, 5, 5, 5));

        JLabel label = new JLabel(key);
        label.setFont(panel.getFont().deriveFont(Font.BOLD, 20f));
        panel.add(label, BorderLayout.NORTH);

        AVTableModel tableModel = new AVTableModel();
        tableModel.addColumns();
        tableModel.addRows(animalValues);

        JTable table = new JTable(tableModel);
        table.setAutoCreateRowSorter(true);
        table.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);

        TableColumnModel columnModel = table.getColumnModel();
        columnModel.getColumn(0).setPreferredWidth(150);
        columnModel.getColumn(1).setPreferredWidth(60);
        columnModel.getColumn(2).setPreferredWidth(100);
        columnModel.getColumn(3).setPreferredWidth(60);
        columnModel.getColumn(4).setPreferredWidth(100);
        columnModel.getColumn(5).setPreferredWidth(100);
        Dimension d = table.getPreferredSize();
        d.width = 570;
        table.setPreferredSize(d);
        table.setPreferredScrollableViewportSize(
                new Dimension(d.width, d.height));

        columnModel.getColumn(1).setCellRenderer(new CenterRenderer());
        columnModel.getColumn(2).setCellRenderer(new CenterRenderer());
        columnModel.getColumn(3).setCellRenderer(new PercentRenderer());
        columnModel.getColumn(4).setCellRenderer(new MoneyRenderer("%,d"));
        columnModel.getColumn(5).setCellRenderer(new MoneyRenderer("%,d"));

        JScrollPane scrollPane = new JScrollPane(table);
        scrollPane.setWheelScrollingEnabled(false);

        panel.add(scrollPane, BorderLayout.CENTER);

        return panel;
    }

    public class CenterRenderer extends DefaultTableCellRenderer {

        private static final long serialVersionUID = 1L;

        @Override
        public Component getTableCellRendererComponent(JTable table,
                Object value, boolean isSelected, boolean hasFocus, int row,
                int column) {
            JLabel label = (JLabel) super.getTableCellRendererComponent(table,
                    value, isSelected, hasFocus, row, column);
            label.setHorizontalAlignment(JLabel.CENTER);
            return label;
        }

    }

    public class MoneyRenderer extends DefaultTableCellRenderer {

        private static final long serialVersionUID = 1L;

        private final String formatter;

        public MoneyRenderer(String formatter) {
            this.formatter = formatter;
        }

        @Override
        public Component getTableCellRendererComponent(JTable table,
                Object value, boolean isSelected, boolean hasFocus, int row,
                int column) {
            JLabel label = (JLabel) super.getTableCellRendererComponent(table,
                    value, isSelected, hasFocus, row, column);
            String s = "";
            if (value instanceof Double) {
                s = String.format(formatter, (double) value);
            } else {
                s = String.format(formatter, (int) value);
            }

            label.setText("$" + s + " ");
            label.setHorizontalAlignment(JLabel.TRAILING);
            return label;
        }

    }

    public class PercentRenderer extends DefaultTableCellRenderer {

        private static final long serialVersionUID = 1L;

        @Override
        public Component getTableCellRendererComponent(JTable table,
                Object value, boolean isSelected, boolean hasFocus, int row,
                int column) {
            JLabel label = (JLabel) super.getTableCellRendererComponent(table,
                    value, isSelected, hasFocus, row, column);
            label.setText(value.toString() + "%");
            label.setHorizontalAlignment(JLabel.CENTER);
            return label;
        }

    }

    public class AVTableModel extends DefaultTableModel {

        private static final long serialVersionUID = 1L;

        public AVTableModel() {
            super();
        }

        public void addColumns() {
            addColumn("Subtype");
            addColumn("Count");
            addColumn("Age in months");
            addColumn("Health");
            addColumn("Current value");
            addColumn("Total value");
        }

        public void addRows(List<AnimalValue> animalValues) {
            for (AnimalValue animalValue : animalValues) {
                Object[] rowData = new Object[this.getColumnCount()];
                rowData[0] = animalValue.getSubType();
                int count = animalValue.getCount();
                rowData[1] = count;
                rowData[2] = animalValue.getAge();
                rowData[3] = animalValue.getHealth();
                int value = animalValue.getValue();
                rowData[4] = value / count;
                rowData[5] = value;
                addRow(rowData);
            }
        }

        @Override
        public boolean isCellEditable(int row, int column) {
            return false;
        }

        @Override
        public Class<?> getColumnClass(int columnIndex) {
            switch (columnIndex) {
            case 0:
                return String.class;
            default:
                return Integer.class;
            }
        }

    }

    public class AnimalModel {

        private Map<String, List<AnimalValue>> animalMap;

        public AnimalModel() {
            this.animalMap = new HashMap<>();
            List<AnimalValue> chickenValues = new ArrayList<>();
            chickenValues.add(new AnimalValue(20, 12, 100, "chicken"));
            chickenValues.add(new AnimalValue(20, 11, 100, "chicken"));
            chickenValues.add(new AnimalValue(20, 10, 100, "chicken"));
            animalMap.put("Chickens", chickenValues);

            List<AnimalValue> duckValues = new ArrayList<>();
            duckValues.add(new AnimalValue(15, 8, 95, "duck"));
            duckValues.add(new AnimalValue(15, 7, 90, "duck"));
            animalMap.put("Ducks", duckValues);
        }

        public Map<String, List<AnimalValue>> getAnimalMap() {
            return animalMap;
        }
    }

    public class AnimalValue {
        private int count;
        private int age;
        private int health;
        private String subType;
        private int value;

        public AnimalValue(int count, int age, int health, String subType) {
            this.count = count;
            this.age = age;
            this.health = health;
            this.subType = subType;
            this.value = count * 150;
        }

        public int getCount() {
            return count;
        }

        public int getAge() {
            return age;
        }

        public int getHealth() {
            return health;
        }

        public String getSubType() {
            return subType;
        }

        public int getValue() {
            return value;
        }
    }
}

备注:内容来源于stack exchange,提问作者Gilbert Le Blanc

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.15 03:44:27