java - JSplitPane 分隔符拖动不适用于复杂布局

标签 java swing jsplitpane

我有一个 Java GUI 程序,其中有一个 JSplitPane 来划分内容。 JSplitPane 的左侧是一个带有许多选项卡的 JTabbedPane - 一个非常复杂的布局。当左侧达到一定的复杂程度时,拖动分隔线来移动分隔线位置不再起作用,但我仍然可以通过显式设置位置来移动分隔线。 (如果重要的话,我正在使用 Nimbus LAF。)

似乎不仅仅是左侧选项卡的数量。我在左侧包含的某些选项卡使其停止工作,而其他选项卡则正常。

有人遇到过这种情况吗?

我能够通过在我的 JSplitPane 子类上添加一个 hack 解决方法来解决这个问题。

    public void enableDividerWorkaround() {
      javax.swing.plaf.basic.BasicSplitPaneUI l_ui = (javax.swing.plaf.basic.BasicSplitPaneUI) getUI();
      BasicSplitPaneDivider l_divider = l_ui.getDivider();

      l_divider.addMouseMotionListener(new MouseMotionAdapter() {
        @Override
        public void mouseDragged(MouseEvent e) {
          Dimension l_pane_size = getSize();
          if (getOrientation() == JSplitPane.HORIZONTAL_SPLIT) {
            int l_new_loc = getDividerLocation() + e.getX();
            if (l_new_loc >= 0 && l_new_loc <= l_pane_size.width) {
              setDividerLocation(l_new_loc);
            }
          } else {
            int l_new_loc = getDividerLocation() + e.getY();
            if (l_new_loc >= 0 && l_new_loc <= l_pane_size.height) {
              setDividerLocation(l_new_loc);
            }
          }
        }
      });
    }

更新 这是 SSCCE(如下)。当我运行此命令时,第一次将 slider 拖动到右侧时,它“捕捉”到长标签的末尾,然后保持固定在那里。我相信这是由长标签引发的。如果我缩短标签, slider 上的运动范围就会更大。那么这是一个错误,还是预期的行为?

    public class SplitPaneTest extends javax.swing.JFrame {
      public SplitPaneTest() {
        initComponents();
      }
      private void initComponents() {

        jSplitPane1 = new javax.swing.JSplitPane();
        jLabel1 = new javax.swing.JLabel();
        jPanel1 = new javax.swing.JPanel();
        jLabel2 = new javax.swing.JLabel();

        setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);

        jSplitPane1.setDividerLocation(450);
        jSplitPane1.setName("jSplitPane1"); 

        jLabel1.setText("right side");
        jLabel1.setName("jLabel1"); 
        jSplitPane1.setRightComponent(jLabel1);

        jPanel1.setName("jPanel1"); 

        jLabel2.setText("left side asd adsf asdf asdf asdf sadf asdf asdf asdf asdf asdf asdf asdf asdf asdf asdf asdfa end");
        jLabel2.setName("jLabel2"); 

        javax.swing.GroupLayout jPanel1Layout = new javax.swing.GroupLayout(jPanel1);
        jPanel1.setLayout(jPanel1Layout);
        jPanel1Layout.setHorizontalGroup(
          jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
          .addGroup(jPanel1Layout.createSequentialGroup()
            .addContainerGap()
            .addComponent(jLabel2)
            .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
        );
        jPanel1Layout.setVerticalGroup(
          jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
          .addGroup(jPanel1Layout.createSequentialGroup()
            .addContainerGap()
            .addComponent(jLabel2)
            .addContainerGap(420, Short.MAX_VALUE))
        );

        jSplitPane1.setLeftComponent(jPanel1);

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
        getContentPane().setLayout(layout);
        layout.setHorizontalGroup(
          layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
          .addComponent(jSplitPane1)
        );
        layout.setVerticalGroup(
          layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
          .addComponent(jSplitPane1)
        );

        pack();
      }

      /**
       * @param args the command line arguments
       */
      public static void main(String args[]) {
        java.awt.EventQueue.invokeLater(new Runnable() {
          public void run() {
            new SplitPaneTest().setVisible(true);
          }
        });
      }
      protected javax.swing.JLabel jLabel1;
      protected javax.swing.JLabel jLabel2;
      protected javax.swing.JPanel jPanel1;
      protected javax.swing.JSplitPane jSplitPane1;
    }

最佳答案

I spent quite a bit of time trying to get to the point of having a SSCCE but was unable to do so

.

  • 请问什么???一个SSCCE最多 5 分钟


  • 现在还有两个问题

    1. SplitPaneUI 也有定义吗,因为 if (ui instanceof BasicSplitPaneUI) { 可以返回漂亮的 false

    2. 说明添加 MouseMotionListener 的原因

<小时/>

EDIT_1。

The left side of the JSplitPane is a JTabbedPane with a number of tabs - a very complex layout. When the left side reaches a certain level of complexity, dragging the divider to move the divider location no longer works, but I can still move the divider by explicitly setting the location.

Distributing Space When a JSplitPane Container Is Resized The weight of a split pane controls the behavior of the divider when the split pane is resized. If the weight is 0, all extra space is given to the right or bottom component. If the weight is 1, all extra space is given to the left or top component. A weight of .3 specifies that the left or top component gets one-third of the extra space. The weight also determines how the children lose space when the size of the split pane is reduced. For example, a weight of 0 means that the left or top component does not lose any space.

The weight also controls the starting location of the divider. For example, if the weight is .5, the divider is placed in the center. COPY

// Create a left-right split pane
JSplitPane pane = new JSplitPane(
     JSplitPane.HORIZONTAL_SPLIT, leftComponent, rightComponent);

// Get current weight
double weight = pane.getResizeWeight();    // 0.0 by default

// Keep the size of the right component constant
weight = 1D;
pane.setResizeWeight(weight);

// Split the space evenly
weight = .5D;
pane.setResizeWeight(weight);
<小时/>

EDIT_2nd。

你忘了告诉我们,在 Nimbus 中,分隔线是否会出现可怕的闪烁,而不是由其余标准 L&F 引起的

<小时/>

enter image description here

import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionAdapter;
import javax.swing.BorderFactory;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JSplitPane;
import javax.swing.JTable;
import javax.swing.plaf.basic.BasicSplitPaneDivider;
import javax.swing.plaf.basic.BasicSplitPaneUI;

public class JSplitPaneToy {

    private JSplitPane sp;

    public JSplitPaneToy() {
        sp = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, makePanel(), makePanel());
        /*SplitPaneUI ui = sp.getUI();
         if (ui instanceof BasicSplitPaneUI) {
         ((BasicSplitPaneUI) ui).getDivider().setBorder(null);
         }*/
        BasicSplitPaneUI l_ui = (BasicSplitPaneUI) sp.getUI();
        BasicSplitPaneDivider l_divider = l_ui.getDivider();
        l_divider.addMouseMotionListener(new MouseMotionAdapter() {
            @Override
            public void mouseDragged(MouseEvent e) {
                Dimension l_pane_size = sp.getSize();
                if (sp.getOrientation() == JSplitPane.HORIZONTAL_SPLIT) {
                    int l_new_loc = sp.getDividerLocation() + e.getX();
                    if (l_new_loc >= 0 && l_new_loc <= l_pane_size.width) {
                        sp.setDividerLocation(l_new_loc);
                    }
                } else {
                    int l_new_loc = sp.getDividerLocation() + e.getY();
                    if (l_new_loc >= 0 && l_new_loc <= l_pane_size.height) {
                        sp.setDividerLocation(l_new_loc);
                    }
                }
            }
        });
        sp.setBorder(BorderFactory.createEmptyBorder());
        /*sp = new JSplitPane(JSplitPane.VERTICAL_SPLIT, makePanel(), sp);
         ui = sp.getUI();
         if (ui instanceof BasicSplitPaneUI) {
         ((BasicSplitPaneUI) ui).getDivider().setBorder(null);
         }
         sp.setBorder(BorderFactory.createEmptyBorder());
         sp = new JSplitPane(JSplitPane.VERTICAL_SPLIT, makePanel(), sp);
         ui = sp.getUI();
         if (ui instanceof BasicSplitPaneUI) {
         ((BasicSplitPaneUI) ui).getDivider().setBorder(null);
         }
         sp.setBorder(BorderFactory.createEmptyBorder());
         sp = new JSplitPane(JSplitPane.VERTICAL_SPLIT, makePanel(), sp);
         ui = sp.getUI();
         if (ui instanceof BasicSplitPaneUI) {
         ((BasicSplitPaneUI) ui).getDivider().setBorder(null);
         }
         sp.setBorder(BorderFactory.createEmptyBorder());*/
        JFrame frame = new JFrame("JSplitPane Toy");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setContentPane(sp);
        frame.pack();
        frame.setVisible(true);
    }

    public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                new JSplitPaneToy();
            }
        });
    }

    private JScrollPane makePanel() {
        JScrollPane pane = new JScrollPane(new JTable(
                new Object[][]{{0, 1, 2}, {1, 2, 3}, {2, 3, 4}}, new Object[]{1, 2, 3}) {
        });
        pane.setPreferredSize(new Dimension(200, 100));
        return pane;
    }
}

关于java - JSplitPane 分隔符拖动不适用于复杂布局,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18644876/

相关文章:

swing - 在SWT中如何实现Swing的JSplitPane?

java - 在 JSplitPane 上设置分隔线位置不起作用

java - codehaus.mojo gwt-maven-插件 : project fails to compile

java - 从字符串中删除自定义标签,然后格式化其内容

java - 递归和 ram 洪水 : Starting a Gradle Daemon, 1 忙 6 停止 守护进程无法重用,使用 --status 了解详情

java - Jtextarea出不来

java - 更改单击的 JTable 单元格的背景颜色

java - 为什么 Java Bean 模式不是线程安全的

Java - 在 JTextField 中输入一些字母后,JFrame 一直卡住

java - JSplitPane 忽略对齐