JSplitPane 内的 JScrollPane 最小宽度

问题描述

我正在试用 JSplitPane 和几个可并排滚动的 JTable
但是,我正在尝试一种行为,根据 gif,JScrollPane 收缩得太多。
请注意左侧组件,除了最小 width250px 外,还会继续缩小。

enter image description here

相关代码

final var objetsTable = new JTable();
final var objectsScrollPane = new JScrollPane(objetsTable);
objectsScrollPane.setMinimumSize(new Dimension(250,0));
objectsScrollPane.setPreferredSize(new Dimension(400,300));

final var stepsTable = new JTable();
final var stepsScrollPane = new JScrollPane(stepsTable);
stepsScrollPane.setMinimumSize(new Dimension(150,0));
stepsScrollPane.setPreferredSize(new Dimension(200,300));

final var splitPane = new JSplitPane();
splitPane.setLeftComponent(objectsScrollPane);
splitPane.setRightComponent(stepsScrollPane);
splitPane.setResizeWeight(1.0);

在这种情况下,如何避免 JScrollPane 收缩太多?

解决方法

getMinimumSize 调用的 JSplitPane 返回的大小实际上考虑了其左右 Component 的最小大小,加上分隔符大小。因此,可能解决您的问题的一种方法是让您的 JSplitPane 实现 Scrollable(以使其尊重自身的最小大小)并将其添加到 JScrollPane。通过这种方式,您可以确保遵守最小尺寸,并且当用户继续缩小 Scrollable JSplitPane 超过其最小尺寸时,滚动条将显示。

这是一些工作代码:

import java.awt.Color;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.Rectangle;
import javax.swing.BorderFactory;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JSplitPane;
import javax.swing.JViewport;
import javax.swing.Scrollable;
import javax.swing.SwingConstants;
import javax.swing.SwingUtilities;

public class Main {
    
    private static class MyScrollableSplitPane extends JSplitPane implements Scrollable {
        
        private int maxUnitIncrement = 10;
        
        public void setMaxUnitIncrement(final int pixels) {
            maxUnitIncrement = pixels;
        }
        
        public int getMaxUnitIncrement() {
            return maxUnitIncrement;
        }
        
        /**
         * This is being constantly checked by the scroll pane instead of the
         * getPreferredScrollableViewportSize...
         */
        @Override
        public Dimension getPreferredSize() {
            final Dimension minSz = getMinimumSize(),curSz = getSize();
            curSz.width = Math.max(curSz.width,minSz.width);
            curSz.height = Math.max(curSz.height,minSz.height);
            return curSz;
        }
        
        /**
         * This is only checked once (at the beginning).
         */
        @Override
        public Dimension getPreferredScrollableViewportSize() {
            return super.getPreferredSize();
        }

        /**
         * Source: https://docs.oracle.com/javase/tutorial/uiswing/components/scrollpane.html .
         */
        @Override
        public int getScrollableUnitIncrement(Rectangle visibleRect,int orientation,int direction) {
            //Get the current position.
            int currentPosition;
            if (orientation == SwingConstants.HORIZONTAL) {
                currentPosition = visibleRect.x;
            } else {
                currentPosition = visibleRect.y;
            }

            //Return the number of pixels between currentPosition
            //and the nearest tick mark in the indicated direction.
            if (direction < 0) {
                int newPosition = currentPosition -
                                 (currentPosition / maxUnitIncrement)
                                  * maxUnitIncrement;
                return (newPosition == 0) ? maxUnitIncrement : newPosition;
            } else {
                return ((currentPosition / maxUnitIncrement) + 1)
                       * maxUnitIncrement
                       - currentPosition;
            }
        }

        /**
         * Source: https://docs.oracle.com/javase/tutorial/uiswing/components/scrollpane.html .
         */
        @Override
        public int getScrollableBlockIncrement(Rectangle visibleRect,int direction) {
            if (orientation == SwingConstants.HORIZONTAL) {
                return visibleRect.width - maxUnitIncrement;
            } else {
                return visibleRect.height - maxUnitIncrement;
            }
        }

        @Override
        public boolean getScrollableTracksViewportWidth() {
            final Container parent = getParent();
            return (parent instanceof JViewport) && (getMinimumSize().width < ((JViewport) parent).getWidth());
        }

        @Override
        public boolean getScrollableTracksViewportHeight() {
            final Container parent = getParent();
            return (parent instanceof JViewport) && (getMinimumSize().height < ((JViewport) parent).getHeight());
        }
    }
    
    private static void createAndShowGUI() {
        
        /*Since I don't add any Components to the 'left' and 'right' panels,I am going to set the
        preferred size of them. This is only for demonstrating the concept. Setting the minimum size
        though is somewhat required by the JSplitPane itself.*/
        
        final JPanel left = new JPanel();
        left.setMinimumSize(new Dimension(150,100));
        left.setPreferredSize(new Dimension(200,200));
        
        final JPanel right = new JPanel();
        right.setMinimumSize(new Dimension(300,100));
        right.setPreferredSize(new Dimension(400,200));
        
        final JSplitPane split = new MyScrollableSplitPane();
        split.setBorder(BorderFactory.createLineBorder(Color.CYAN.darker(),3));
        split.setOrientation(JSplitPane.HORIZONTAL_SPLIT);
        split.setLeftComponent(left);
        split.setRightComponent(right);
        
        final JFrame frame = new JFrame("MyScrollableSplitPane demo");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.getContentPane().add(new JScrollPane(split));
        frame.pack();
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    }
    
    public static void main(final String[] args) {
        SwingUtilities.invokeLater(Main::createAndShowGUI);
    }
}

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...