【问题标题】:Set JSplitPane divider location from the right从右侧设置 JSplitPane 分隔线位置
【发布时间】:2021-02-05 18:11:33
【问题描述】:

据我所知,JSplitPane 的setDivider() 方法可以采用从左侧算起的绝对位置的 int。例如,someSplitPane.setDivider(120); 会将分隔线设置为距左侧 120 像素。有什么办法可以做同样的事情,但将分隔线设置为从右侧开始的绝对位置?

简单实现:

public class Window extends JFrame {
    
    JSplitPane splitpane;
    
    public Window() {
        initComponents();
    }
    
    private void initComponents() {
        setTitle("Debugging");
        setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        setMinimumSize(new Dimension(640, 480));
        
        splitpane = new JSplitPane();
        System.out.println(splitpane.getSize().width); // prints 0
        splitpane.setDividerLocation(splitpane.getSize().width - 120);
        getContentPane().add(splitpane);
    }
    
    public static void main(String[] args) {
        
        SwingUtilities.invokeLater(() -> {
            new Window().setVisible(true);
        });
    }
}

编辑:我已经编写了与任何现有代码隔离的代码,并且我重现了该错误。看起来正在发生的事情是 JFrame 正在实例化并出现在桌面上,然后大约一秒钟后,一个 0(来自注释的打印语句)输出到控制台。

【问题讨论】:

    标签: java swing user-interface jsplitpane


    【解决方案1】:

    假设您使用 EDT 正确创建了 GUI,您可以在创建 splitPane 的类的构造函数中添加以下内容:

    SwingUtilities.invokeLater(() ->
    {
            Dimension d = splitPane.getSize();
            splitPane.setDividerLocation(d.width - 120);
    });
    

    这会将代码添加到 EDT。因此,在框架可见并且已为拆分窗格指定大小后,将重置分隔线位置。

    【讨论】:

    • 我确实在使用 EDT。在 EDT 内部,我实例化了一个新的 JFrame,它又在其构造函数中实例化了 JScrollPane。我将更新问题以反映此信息。我尝试了您的解决方案(以及splitpane.getWidth() - 100),两次结果都是-100,而不是宽度 - 100。
    • 对我来说很好。发布您的minimal reproducible example 来证明问题。
    • 唉,我的问题和往常一样,还有其他事情在我的雷达下飞行。给我一点时间尝试尽可能少地复制问题,而不是做出假设。
    • 我已将代码更新为我认为仍然重现问题所必需的最少代码(这次经过测试确定)。
    • 我说你需要在你的类的构造函数中添加上面的代码。关键是您的整个 GUI 是在 EDT 上创建的,但是在框架可见并且所有组件都已指定大小之前,您不知道拆分窗格的大小。所以你需要第二个 invokeLater()。
    【解决方案2】:

    我对您的代码进行了一些更改并创建了这个 GUI。

    我使用了JFrame,而不是扩展JFrame

    我设置了JSplitPane 的首选大小,而不是JFrame。通常,您更关心JSplitPane 的大小而不是JFrame。通常,JSplitPane 将有两个带有 Swing 组件的JPanels,因此您不必在此时指定首选大小。

    这是完整的可运行代码。

    import java.awt.BorderLayout;
    import java.awt.Dimension;
    
    import javax.swing.JFrame;
    import javax.swing.JSplitPane;
    import javax.swing.SwingUtilities;
    
    public class JSplitPaneRight {
    
        public static void main(String[] args) {
            SwingUtilities.invokeLater(() -> {
                new JSplitPaneRight();
            });
        }
        
        public JSplitPaneRight() {
            initComponents();
        }
        
        public void initComponents() {
            JFrame frame = new JFrame("JSplitPane Right");
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            
            frame.add(createSplitPane(), BorderLayout.CENTER);
            
            frame.pack();
            frame.setLocationByPlatform(true);
            frame.setVisible(true);
        }
        
        private JSplitPane createSplitPane( ) {
            JSplitPane splitpane = new JSplitPane();
            splitpane.setPreferredSize(new Dimension(640, 480));
            int width = splitpane.getPreferredSize().width;
            System.out.println(width); // prints 0
            splitpane.setDividerLocation(width - 120);
            
            return splitpane;
        }
    
    }
    

    【讨论】:

    • 如果您知道 JSplitPane 的大小,这是一个很好的方法。
    • @Mike:正如我在回答中解释的那样,一旦您使用 Swing 组件创建了两个 JPanel,您就不再需要定义 JSplitPane 的首选大小。布局管理器将计算首选尺寸。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2023-03-20
    • 2017-03-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多