【问题标题】:JSplitPane: is there a way to show/hide one of the panes?JSplitPane:有没有办法显示/隐藏其中一个窗格?
【发布时间】:2011-10-13 18:00:44
【问题描述】:

我有一个包含两个组件 A 和 B 的 JSplitPane,但有时我希望能够隐藏 B,以便以下任一情况为真:

  • 组件 A 和 B 在 JSplitPane 中可见
  • 在 JSplitPane 占用的空间中只有组件 A 可见

有没有办法做到这一点?

【问题讨论】:

    标签: java swing jsplitpane


    【解决方案1】:

    哎呀,我会尝试解决方案......

    import java.awt.Dimension;
    import java.awt.event.*;
    import javax.swing.*;
    
    public class Test {
       public static void main(String[] args) {
          JFrame frame = new JFrame();
          final JPanel contentPane = (JPanel)frame.getContentPane();
    
          final JButton leftBtn = new JButton("Left Button");
          final JButton rightBtn = new JButton("Right Button");
          final JSplitPane jsp = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT,
                leftBtn, rightBtn);
          ActionListener actionListener = new ActionListener() {
             public void actionPerformed(ActionEvent e) {
                JButton source = (JButton)e.getSource();
                if (jsp.isVisible()) {
                   jsp.remove(rightBtn);
                   jsp.remove(leftBtn);
                   jsp.setVisible(false);
                   contentPane.removeAll();
                   contentPane.add(source);
                } else {
                   contentPane.removeAll();
                   jsp.setLeftComponent(leftBtn);
                   jsp.setRightComponent(rightBtn);
                   jsp.setDividerLocation(0.5);
                   jsp.setVisible(true);
                   contentPane.add(jsp);
                }
                contentPane.revalidate();
                contentPane.repaint();
                source.requestFocusInWindow();
             }
          };
          rightBtn.addActionListener(actionListener);
          leftBtn.addActionListener(actionListener);
          contentPane.add(jsp);
          contentPane.setPreferredSize(new Dimension(800, 600));
          frame.pack();
          frame.setLocationRelativeTo(null);
          frame.setVisible(true);
          jsp.setDividerLocation(0.5);
          frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
       }
    }
    

    【讨论】:

    • 喜欢你的例子 +1,source.requestFocusInWindow(); 将被包装成 invokeLater
    【解决方案2】:

    我发现 Hovercraft Full Of Eels 的版本存在问题并制作了自己的版本。

    Hovercraft Full Of Eels 的作品,但是如果单击按钮,调整框架大小,然后再次单击按钮,则会出现图形错误;也如 amol 所说,您可能希望在此过程中保留拆分器位置。

    import java.awt.event.ActionEvent;
    import java.awt.event.ActionListener;
    
    import javax.swing.JButton;
    import javax.swing.JFrame;
    import javax.swing.JPanel;
    import javax.swing.JSplitPane;
    import javax.swing.UIManager;
    
    public class JSplitPaneShowHidePane {
        public static void main(String[] args) {
            JFrame frame = new JFrame();
            JPanel contentPane = (JPanel)frame.getContentPane();
    
            final JButton leftBtn = new JButton("Left Button");
            final JButton rightBtn = new JButton("Right Button");
            final JSplitPane jsp = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT,
                    leftBtn, rightBtn);
            ActionListener actionListener = new ActionListener() {
                private int loc = 0;
                public void actionPerformed(ActionEvent e) {
                    JButton source = (JButton)e.getSource();
                    if(jsp.getLeftComponent().isVisible() && jsp.getRightComponent().isVisible()){
                        loc = jsp.getDividerLocation();
                        jsp.setDividerSize(0);
                        jsp.getLeftComponent().setVisible(source == leftBtn);
                        jsp.getRightComponent().setVisible(source == rightBtn);
                    }else{
                        jsp.getLeftComponent().setVisible(true);
                        jsp.getRightComponent().setVisible(true);
                        jsp.setDividerLocation(loc);
                        jsp.setDividerSize((Integer) UIManager.get("SplitPane.dividerSize"));
                    }
                }
            };
            rightBtn.addActionListener(actionListener);
            leftBtn.addActionListener(actionListener);
            contentPane.add(jsp);
            frame.pack();
            frame.setSize(800, 600);
            frame.setLocationRelativeTo(null);
            frame.setVisible(true);
            jsp.setDividerLocation(0.5);
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        }
    }
    

    【讨论】:

    • 很好的解决方案!但是,我发现有必要在隐藏右侧组件后调用 jsp.setDividerLocation(1.0),在隐藏左侧组件后调用 jsp.setDividerLocation(0.0),以确保在用户调整窗口大小时可见组件继续填充窗口。
    【解决方案3】:

    假设 HORIZONTAL_SPLIT 拆分为两个组件(左侧为 A,右侧为 B)

    下面是隐藏 A 并让 B 占用所有拆分窗格空间的方法

    
    myButton.addActionListener(new ActionListener() {
        @Override
        public void actionPerformed(ActionEvent e) {
            mySplitPane.setDividerSize(0);
            mySplitPane.setDividerLocation(mySplitPane.getLocation().x);
        }
    });
    

    隐藏组件 B 并显示 A -

    
    ...
      mySplitPane.setDividerLocation(pane.getLocation().x+pane.getSize().width);
    ...
    

    如果您有垂直拆分,请使用类似的方法并将xywidthheight 切换

    对于一个完整的解决方案,您必须监听调整大小事件(如果适用)并重新计算分隔线位置(这意味着您将存储当前在某处可见的状态)

    【讨论】:

    • 什么是pane是splitpane吗?
    【解决方案4】:

    如果您引用了组件 A 和 B,您可以使用组件 A 或 B 的 JSplitPane.remove() 方法JComponent.setVisible(false) 方法

    测试代码:

        final JFrame f = new JFrame();
        final JSplitPane jsp = new JSplitPane();
        final JButton leftB = new JButton("Left: Hide Self");
        final JButton rightB = new JButton("Right: Show Left");
        jsp.setOneTouchExpandable(true);
        leftB.addActionListener(new ActionListener() {
            @Override public void actionPerformed(ActionEvent e) {
                jsp.remove(leftB);
            }
        });
        rightB.addActionListener(new ActionListener() {
            @Override public void actionPerformed(ActionEvent e) {
                jsp.setLeftComponent(leftB);
            }
        });
        jsp.setLeftComponent(leftB);
        jsp.setRightComponent(rightB);
        f.add(jsp);
        f.setSize(800, 600);
        f.setVisible(true);
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    

    【讨论】:

    • setVisible(false) 不满足 Jason 的第二个项目符号。 (组件 A 应该占据 splitpane 拥有的所有可见空间)
    • +1 表示它,但@amol 是对的——我试过了,它仍然让分离器可见。此外,当您在该组件上恢复 setVisible(true) 时,拆分器位置不会恢复其原始位置。
    • 查看充满鳗鱼的气垫船代码。似乎必须重新设计组件,哈哈。
    【解决方案5】:

    我用它来切换框架底部的日志面板:

    private void toggleLogPanel() 
    {
      if(m_logPanel.isShowing())
      {
        m_logDimension = m_logPanel.getSize();
        m_splitpane.setBottomComponent(null);
        m_splitpane.setDividerSize(0);
      }
      else
      {
        m_logPanel.setPreferredSize(m_logDimension);
        m_splitpane.setBottomComponent(m_logPanel);
        m_splitpane.setDividerSize(new JSplitpane().getDividerSize());
      }
    
      m_splitpane.resetToPreferredSizes();
    }
    

    这会记住并恢复组件大小。

    【讨论】:

      【解决方案6】:

      试试ExpandableSplitPane#setOneSideHidden

      package com.legendmohe.tool.view;
      
      import java.awt.Component;
      import java.awt.event.ActionEvent;
      import java.awt.event.ActionListener;
      import java.lang.reflect.Field;
      
      import javax.swing.JButton;
      import javax.swing.JSplitPane;
      import javax.swing.plaf.basic.BasicSplitPaneDivider;
      import javax.swing.plaf.basic.BasicSplitPaneUI;
      
      /**
       * Created by legendmohe on 2019/4/16.
       */
      public class ExpandableSplitPane extends JSplitPane {
      
          private HiddenListener mHiddenListener;
      
          private JButton mLeftButton;
      
          private JButton mRightButton;
      
          //////////////////////////////////////////////////////////////////////
      
          public ExpandableSplitPane() {
          }
      
          public ExpandableSplitPane(int newOrientation) {
              super(newOrientation);
          }
      
          public ExpandableSplitPane(int newOrientation, boolean newContinuousLayout) {
              super(newOrientation, newContinuousLayout);
          }
      
          public ExpandableSplitPane(int newOrientation, Component newLeftComponent, Component newRightComponent) {
              super(newOrientation, newLeftComponent, newRightComponent);
          }
      
          public ExpandableSplitPane(int newOrientation, boolean newContinuousLayout, Component newLeftComponent, Component newRightComponent) {
              super(newOrientation, newContinuousLayout, newLeftComponent, newRightComponent);
          }
      
          //////////////////////////////////////////////////////////////////////
      
          public void setOneSideHidden(Component whichSide, boolean isHidden) {
              if (whichSide == getLeftComponent()) {
                  // if right commponent hidden
                  if (isRightComponentHidden()) {
                      // show right and hide left
                      if (isHidden) {
                          clickDividerButton(mLeftButton);
                          clickDividerButton(mLeftButton);
                      }
                  } else if (isLeftComponentHidden()) {
                      // show left
                      if (!isHidden) {
                          clickDividerButton(mRightButton);
                      }
                  } else {
                      if (isHidden) {
                          clickDividerButton(mLeftButton);
                      }
                  }
              } else if (whichSide == getRightComponent()) {
                  // if left commponent hidden
                  if (isLeftComponentHidden()) {
                      // show right and hide left
                      if (isHidden) {
                          clickDividerButton(mRightButton);
                          clickDividerButton(mRightButton);
                      }
                  } else if (isRightComponentHidden()) {
                      // show left
                      if (!isHidden) {
                          clickDividerButton(mRightButton);
                      }
                  } else {
                      if (isHidden) {
                          clickDividerButton(mRightButton);
                      }
                  }
              }
          }
      
          public boolean isSideHidden(Component whichSide) {
              if (whichSide == getLeftComponent()) {
                  return isLeftComponentHidden();
              } else if (whichSide == getRightComponent()) {
                  return isRightComponentHidden();
              }
              return false;
          }
      
          @Override
          public void setOneTouchExpandable(boolean expandable) {
              super.setOneTouchExpandable(expandable);
              if (expandable) {
                  final BasicSplitPaneUI ui = ((BasicSplitPaneUI) getUI());
      
                  Field keepHidden = null;
                  try {
                      keepHidden = BasicSplitPaneUI.class.getDeclaredField("keepHidden");
                      keepHidden.setAccessible(true);
                  } catch (NoSuchFieldException e) {
                      e.printStackTrace();
                  }
                  final Field finalKeepHidden = keepHidden;
      
                  BasicSplitPaneDivider divider = ui.getDivider();
                  try {
                      Field leftButton = BasicSplitPaneDivider.class.getDeclaredField("leftButton");
                      leftButton.setAccessible(true);
                      Field rightButton = BasicSplitPaneDivider.class.getDeclaredField("rightButton");
                      rightButton.setAccessible(true);
      
                      mLeftButton = (JButton) leftButton.get(divider);
                      mRightButton = (JButton) rightButton.get(divider);
      
                      mLeftButton.addActionListener(new ActionListener() {
                          @Override
                          public void actionPerformed(ActionEvent e) {
                              try {
                                  boolean keepHidden = (boolean) finalKeepHidden.get(ui);
                                  handleActionPerformed(mLeftButton, keepHidden);
                              } catch (IllegalAccessException ex) {
                                  ex.printStackTrace();
                              }
                          }
                      });
                      mRightButton.addActionListener(new ActionListener() {
                          @Override
                          public void actionPerformed(ActionEvent e) {
                              try {
                                  boolean keepHidden = (boolean) finalKeepHidden.get(ui);
                                  handleActionPerformed(mRightButton, keepHidden);
                              } catch (IllegalAccessException ex) {
                                  ex.printStackTrace();
                              }
                          }
                      });
                  } catch (NoSuchFieldException | IllegalAccessException e) {
                      e.printStackTrace();
                  }
              } else {
                  mRightButton = mLeftButton = null;
              }
          }
      
          ///////////////////////////////////private///////////////////////////////////
      
          private void handleActionPerformed(JButton whichButton, boolean keepHidden) {
              if (mHiddenListener != null) {
                  if (whichButton == mLeftButton) {
                      if (isNoSideHidden() && !keepHidden) {
                          mHiddenListener.onStateChanged(this, getLeftComponent(), true);
                      } else if (isRightComponentHidden() && keepHidden) {
                          mHiddenListener.onStateChanged(this, getRightComponent(), false);
                      }
                  } else if (whichButton == mRightButton) {
                      if (isNoSideHidden() && !keepHidden) {
                          mHiddenListener.onStateChanged(this, getRightComponent(), true);
                      } else if (isLeftComponentHidden() && keepHidden) {
                          mHiddenListener.onStateChanged(this, getLeftComponent(), false);
                      }
                  }
              }
          }
      
          private void clickDividerButton(JButton leftButton) {
              leftButton.doClick();
          }
      
          private boolean isNoSideHidden() {
              return (getDividerLocation() >= getMinimumDividerLocation()) && (getDividerLocation() <= getMaximumDividerLocation());
          }
      
          private boolean isLeftComponentHidden() {
              return getDividerLocation() <= getMinimumDividerLocation();
          }
      
          private boolean isRightComponentHidden() {
              return getDividerLocation() >= getMaximumDividerLocation();
          }
      
          ///////////////////////////////////listener///////////////////////////////////
      
          public void setHiddenListener(HiddenListener hiddenListener) {
              mHiddenListener = hiddenListener;
          }
      
          public interface HiddenListener {
              void onStateChanged(ExpandableSplitPane pane, Component whichSide, boolean hidden);
          }
      }
      

      【讨论】:

      • 我会试一试,但这个问题是8年前我在另一家公司时提出的。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-04-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-07-11
      相关资源
      最近更新 更多