Java 如何使用JToggleButtons、jpanel和JScrollPanes解决这些大小调整问题?
我正在尝试开发一种手风琴菜单。有少量(2-12)选项可切换开/关。当切换到on时,将出现一个带有附加设置的Java 如何使用JToggleButtons、jpanel和JScrollPanes解决这些大小调整问题?,java,swing,jpanel,jscrollpane,preferredsize,Java,Swing,Jpanel,Jscrollpane,Preferredsize,我正在尝试开发一种手风琴菜单。有少量(2-12)选项可切换开/关。当切换到on时,将出现一个带有附加设置的JPanel。禁用时,附加设置将不可见 我创建了一个SelectableExpandablePanel类,该类扩展了JPanel,并实现了ActionListener和ComponentListener。该面板包含两件东西-一个JToggleButton和一个子组件(通常是一个JPanel,但我不想限制自己在BoxLayout中执行一个列。选择“切换”按钮后,子对象将可见。取消选择切换时,子
JPanel
。禁用时,附加设置将不可见
我创建了一个SelectableExpandablePanel
类,该类扩展了JPanel
,并实现了ActionListener
和ComponentListener
。该面板包含两件东西-一个JToggleButton
和一个子组件
(通常是一个JPanel,但我不想限制自己在BoxLayout
中执行一个列。选择“切换”按钮后,子对象将可见。取消选择切换时,子对象将隐藏
当我使用这个组件时,我打算将它放在JScrollPane
内部的JPanel上,如示例main方法中所示
似乎有两个问题我很难克服:
如果我不指定一个JFrame
大小,它只够每个子对象的宽度,够三个按钮的高度。当我单击按钮时,我希望JScrollPane
能够完成它的工作并生成一个垂直滚动条。这不会发生
我希望切换按钮是包含它们的JPanel的全宽。我认为我在构造函数中所做的加上组件侦听器
可以处理这个问题,但事实并非如此
下面提供的内容编译并具有主方法。如果编译并执行,它将驱动我正在构建的组件,以提供一个测试框架和重现我所说问题的能力
import javax.swing.BoxLayout;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JToggleButton;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ComponentEvent;
import java.awt.event.ComponentListener;
public class SelectableExpandablePanel extends JPanel implements
ActionListener, ComponentListener {
private JToggleButton titleButton;
private JComponent childComponent;
public SelectableExpandablePanel(JComponent child) {
this(child, null, null);
}
public SelectableExpandablePanel(JComponent child, String title) {
this(child, title, null);
}
public SelectableExpandablePanel(JComponent child, String title,
String tooltip) {
super();
if (child == null) {
throw new IllegalArgumentException("Child component cannot be null");
}
childComponent = child;
titleButton = new JToggleButton();
titleButton.setText(title);
titleButton.addActionListener(this);
titleButton.setPreferredSize(new Dimension(getSize().width, titleButton
.getPreferredSize().height));
titleButton.setToolTipText(tooltip);
setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
setPreferredSize(new Dimension(childComponent.getPreferredSize().width,
titleButton.getPreferredSize().height));
setSize(new Dimension(childComponent.getPreferredSize().width,
titleButton.getPreferredSize().height));
add(titleButton);
this.addComponentListener(this);
}
public void actionPerformed(ActionEvent e) {
if (titleButton.isSelected()) {
add(childComponent);
setSize(new Dimension(childComponent.getPreferredSize().width,
titleButton.getPreferredSize().height
+ childComponent.getPreferredSize().height));
} else {
remove(childComponent);
setSize(new Dimension(childComponent.getPreferredSize().width,
titleButton.getPreferredSize().height));
}
invalidate();
revalidate();
}
public void componentHidden(ComponentEvent arg0) {
// Do nothing
}
public void componentMoved(ComponentEvent arg0) {
// Do nothing
}
public void componentResized(ComponentEvent arg0) {
titleButton.setSize(this.getWidth(),
titleButton.getPreferredSize().height);
}
public void componentShown(ComponentEvent arg0) {
// Do nothing
}
public static void main(String[] args) {
JScrollPane scrollPane = new JScrollPane();
// These panels simulates a complex, multi-line configuration panel.
JPanel testPanel = new JPanel();
testPanel.setLayout(new BoxLayout(testPanel, BoxLayout.Y_AXIS));
testPanel.add(new JLabel("Test JLabel"));
testPanel.add(new JLabel("Test JLabel 2"));
testPanel.add(new JLabel("Test JLabel 3"));
JPanel testPanel2 = new JPanel();
testPanel2.setLayout(new BoxLayout(testPanel2, BoxLayout.Y_AXIS));
testPanel2.add(new JLabel("Test JLabel"));
testPanel2.add(new JLabel("Test JLabel 2"));
testPanel2.add(new JLabel("Test JLabel 3"));
JPanel testPanel3 = new JPanel();
testPanel3.setLayout(new BoxLayout(testPanel3, BoxLayout.Y_AXIS));
testPanel3.add(new JLabel("Test JLabel"));
testPanel3.add(new JLabel("Test JLabel 2"));
testPanel3.add(new JLabel("Test JLabel 3"));
// This panel simulates the panel that will contain each of the
// SelectableExpandablePanels.
JPanel testHolder = new JPanel();
testHolder.setLayout(new BoxLayout(testHolder, BoxLayout.Y_AXIS));
testHolder.add(new SelectableExpandablePanel(testPanel, "Test"));
testHolder.add(new SelectableExpandablePanel(testPanel2, "Test 2"));
testHolder.add(new SelectableExpandablePanel(testPanel3, "Test 3"));
// We add the test holder to the scroll pane. The intention is that if
// the expansion is too big to fit, the holding JFrame won't expand, but
// the scroll pane will get scroll bars to let the user scroll up and
// down through the toggle buttons and any enabled items.
scrollPane.setViewportView(testHolder);
JFrame testFrame = new JFrame("Expandable Panel Test");
testFrame.getContentPane().add(scrollPane);
testFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
testFrame.pack();
testFrame.setVisible(true);
}
}
不要试图自己管理尺寸:
//titleButton.setPreferredSize(new Dimension(getSize().width, titleButton.getPreferredSize().height));
titleButton.setToolTipText(tooltip);
setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
//setPreferredSize(new Dimension(childComponent.getPreferredSize().width, titleButton.getPreferredSize().height));
//setSize(new Dimension(childComponent.getPreferredSize().width, titleButton.getPreferredSize().height));
另外,去掉ActionListener中的setSize()
代码。这将被忽略,因为布局管理器将确定大小
当面板的首选大小大于滚动窗格的大小时,将显示滚动条。如果硬编码首选尺寸,则默认布局管理器的用途,并且在添加/删除零部件时首选尺寸不会更改
注:对于类似的内容,我通常使用边界布局。将按钮放在页面开始处,另一个面板放在中间。组件将自动填满可用空间。不要试图自己管理尺寸:
//titleButton.setPreferredSize(new Dimension(getSize().width, titleButton.getPreferredSize().height));
titleButton.setToolTipText(tooltip);
setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
//setPreferredSize(new Dimension(childComponent.getPreferredSize().width, titleButton.getPreferredSize().height));
//setSize(new Dimension(childComponent.getPreferredSize().width, titleButton.getPreferredSize().height));
另外,去掉ActionListener中的setSize()
代码。这将被忽略,因为布局管理器将确定大小
当面板的首选大小大于滚动窗格的大小时,将显示滚动条。如果硬编码首选尺寸,则默认布局管理器的用途,并且在添加/删除零部件时首选尺寸不会更改
注:对于类似的内容,我通常使用边界布局。将按钮放在页面开始处,另一个面板放在中间。组件将自动填充可用空间
删除所有setSize/setPreferredSize调用,让LayoutManager完成它的工作李>
要允许JButtons填充面板的宽度,可以使用BorderLayout(例如,将按钮添加到中心,将子容器添加到南部,并删除所有这些setSize值,以让LayoutManager处理它)李>
删除所有setSize/setPreferredSize调用,让LayoutManager完成它的工作李>
要允许JButtons填充面板的宽度,可以使用BorderLayout(例如,将按钮添加到中心,将子容器添加到南部,并删除所有这些setSize值,以让LayoutManager处理它)李>
或者,一切都取决于孩子们是什么、如何、何时(如果是或不是)resizable@mKorbel让我看看那些。快速看,使用setVisible而不是添加或删除可能是更好的选择。我需要深入挖掘滚动窗格问题和宽度问题。使用setVisible而不是添加或删除可能会更好--->在JScrollPane内部无所谓,我的问题是you@mKorbel我不知道你在问什么。子面板可以调整大小,是的。一切取决于JFrames childs(如果是或不是)可以调整大小的内容、方式、时间(您期望什么),然后答案更简单,或者一切取决于JFrames childs(如果是或不是)可以调整大小的内容、方式、时间resizable@mKorbel让我看看那些。快速看,使用setVisible而不是添加或删除可能是更好的选择。我需要深入挖掘滚动窗格问题和宽度问题。使用setVisible而不是添加或删除可能会更好--->在JScrollPane内部无所谓,我的问题是you@mKorbel我不知道你在问什么。子面板可以调整大小,是的。一切都取决于什么、如何、何时(您期望什么)JFrames子面板(如果是或不是)可以调整大小,然后答案是更容易这是完美的。我想。我需要进行更多测试,但这看起来像我需要的功能。不要使用setPreferredSize(),这是布局管理器的工作。唯一的问题是,如果我删除setSize/setPreferredSize,SelectableExpandablePanel的大小只是按钮的宽度。宽度必须是最宽的子组件的宽度,因为我想防止水平滚动。除此之外,一切正常。同意关于setPreferredSize()的通知,但另一种情况是JScrollpane(在他的回答中未提及)这是完美的。我想。我需要进行更多测试,但这看起来像我需要的功能。不要使用setPreferredSize(),这是布局管理器的工作。唯一的问题是,如果我删除setSize/setPreferredSize,SelectableExpandablePanel的大小为o