JSplitPane 内的 JScrollPane 最小宽度

如何解决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);
    }
}

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其他元素将获得点击?
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。)
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbcDriver发生异常。为什么?
这是用Java进行XML解析的最佳库。
Java的PriorityQueue的内置迭代器不会以任何特定顺序遍历数据结构。为什么?
如何在Java中聆听按键时移动图像。
Java“Program to an interface”。这是什么意思?
Java在半透明框架/面板/组件上重新绘画。
Java“ Class.forName()”和“ Class.forName()。newInstance()”之间有什么区别?
在此环境中不提供编译器。也许是在JRE而不是JDK上运行?
Java用相同的方法在一个类中实现两个接口。哪种接口方法被覆盖?
Java 什么是Runtime.getRuntime()。totalMemory()和freeMemory()?
java.library.path中的java.lang.UnsatisfiedLinkError否*****。dll
JavaFX“位置是必需的。” 即使在同一包装中
Java 导入两个具有相同名称的类。怎么处理?
Java 是否应该在HttpServletResponse.getOutputStream()/。getWriter()上调用.close()?
Java RegEx元字符(。)和普通点?