java JSplitPane:有没有办法显示/隐藏其中一个窗格?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/6836164/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-30 17:30:19  来源:igfitidea点击:

JSplitPane: is there a way to show/hide one of the panes?

javaswingjsplitpane

提问by Jason S

I have a JSplitPane with two components, A and B, but sometimes I want to be able to hide B, so that either of the following are true:

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

  • components A and B are visible in the JSplitPane
  • only component A is visible in the space occupied by the JSplitPane
  • 组件 A 和 B 在 JSplitPane 中可见
  • 在 JSplitPane 占用的空间中只有组件 A 可见

Is there a way to do this?

有没有办法做到这一点?

回答by Hovercraft Full Of Eels

Heck, I'll throw in an attempt at a solution...

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

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);
   }
}

回答by ron190

I found problems with Hovercraft Full Of Eels' version and made my own.

我发现了充满鳗鱼的气垫船版本的问题并制作了我自己的版本。

Hovercraft Full Of Eels' one works, nevertheless graphical bug appears if you click a button, resize the frame, then click again the button ; also like amol said, you may want the splitter position to remain during the process.

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);
    }
}

回答by user802421

If you have references to the component A and B you could user JSplitPane.remove()method or JComponent.setVisible(false)method of the component A or B.

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

Test code:

测试代码:

    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);

回答by Amol Katdare

Assume HORIZONTAL_SPLIT split with two components (A on left and B on right)

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

Here is how you would hide A and let B take up all the splitpane's space

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


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

To hide component B and show A -

隐藏组件 B 并显示 A -


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

If you have a vertical split, use similar approach and switch xwith yand widthwith height

如果你有一个垂直分割,使用类似的方法和开关xywidthheight

For a complete solution, you will have to listen to resize events (if applicable) and recalculate the divider location (which means you will have store the state of what is currently visible somewhere)

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

回答by Reto H?hener

I use this to toggle a log panel at the bottom of a frame:

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

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();
}

This remembers and restores the component size.

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

回答by legendmohe

try ExpandableSplitPane#setOneSideHidden

尝试 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);
    }
}