如何阻止内部JScrollPane消耗鼠标滚轮滚动事件
如何阻止内部JScrollPane消耗鼠标滚轮滚动事件
我正在组装一个包含多个JTable的JPanel——每个JTable都被JScrollPane包裹,这样表头能正常显示;而整个JPanel又套了一层外层的JScrollPane。
我特意把外层JScrollPane的首选尺寸设得比较小,让垂直滚动条显示出来,效果如下:

但现在遇到个问题:用鼠标滚轮滚动的时候,只有鼠标指针在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
相关产品推荐
相关产品推荐

