【发布时间】:2015-06-29 03:05:00
【问题描述】:
我正在尝试开发一种手风琴菜单形式。有少数 (2-12) 个选项可以打开/关闭。打开时,将有一个JPanel,其中包含可见的其他设置。关闭后,其他设置将不可见。
我创建了一个 SelectableExpandablePanel 类,它扩展了 JPanel 并实现了 ActionListener 和 ComponentListener。该面板包含两个东西 - 一个JToggleButton 和一个孩子Component(通常是一个JPanel,但我不想限制自己以供将来重用这个概念)在BoxLayout 中强制执行一列。选择切换按钮时,子项变为可见。取消选择切换时,子项被隐藏。
当我使用这个组件时,我打算把它放在JScrollPane 内部的JPanel 上,如示例 main 方法中所示。
似乎有两个问题我难以克服:
-
1234563当我点击按钮时,我希望
我希望切换按钮是包含它们的 JPanel 的整个宽度。我以为我在构造函数中所做的加上
Component Listener会处理这个问题,但事实并非如此。
JScrollPane 会做它的事情并生成一个垂直滚动条。这不会发生。
下面提供的内容是编译并有一个 main 方法。如果编译并执行,它会驱动我正在构建的组件以提供测试框架和重现我正在谈论的问题的能力。
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);
}
}
【问题讨论】:
-
-
@mKorbel 让我看看那些。快速查看,看起来使用 setVisible 而不是添加或删除可能是一个更好的选择。我需要深入挖掘滚动窗格问题和宽度问题。
-
使用 setVisible 而不是添加或删除可能会更好 ---> 在 JScrollPane 中无关紧要,是关于我的问题
-
@mKorbel 我不知道你在问什么。子面板可以调整大小,是的。
-
一切都取决于什么、如何、何时(您期望什么)JFrames 子项(如果是或不是)可调整大小,那么答案会更容易
标签: java swing jpanel jscrollpane preferredsize