Я пытаюсь разработать форму гармонического меню. Есть небольшое количество (2-12) опций, которые можно переключать вкл/выкл. При включении появится JPanel
с дополнительными настройками, которые станут видимыми. При переключении дополнительные настройки не будут видны.Как решить эти проблемы с размерами с помощью JToggleButtons, JPanels и JScrollPanes?
Я создал SelectableExpandablePanel
класс, который расширяет JPanel
и реализует ActionListener
и ComponentListener
. Панель содержит две вещи: JToggleButton
и ребенок Component
(обычно это JPanel, но я не хочу ограничивать себя для повторного использования этой концепции) в BoxLayout
для обеспечения соблюдения одного столбца. Когда выбрана кнопка переключения, ребенок становится видимым. Когда переключатель не выбран, ребенок скрыт.
Когда я использую этот компонент, я намерен разместить его на JPanel
внутри JScrollPane
, как показано в основном методе образца.
Там, кажется, две проблемы, которые у меня возникают проблемы с преодолением:
Если я не указать
JFrame
размер, достаточно только большой по ширине каждого ребенка и достаточно высокий для трех кнопок. Когда я нажимаю на кнопку, я ожидаю, чтоJScrollPane
выполнит свою задачу и создаст вертикальную полосу прокрутки. Этого не происходит.Я бы хотел, чтобы кнопки переключения были полной шириной JPanel, которая их содержит. Я думал, что то, что я сделал в конструкторе плюс
Component Listener
, обработало бы это, но это не так.
То, что представлено ниже, компилируется и имеет основной метод. Если он скомпилирован и выполнен, он управляет компонентом, который я создаю, чтобы предоставить тестовый кадр и возможность воспроизводить проблемы, о которых я говорю.
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);
}
}
[DYM] (http://stackoverflow.com/a/8166223/714968) или [DYM] (http: // stackoverflow.com/a/11261110/714968), все зависит от того, что, как, когда дети JFrames (если да или нет) изменяются по размеру – mKorbel
@mKorbel Позвольте мне взглянуть на них. Глядя быстро, похоже, что использование setVisible вместо добавления или удаления скорее всего будет лучшей ставкой. Мне нужно глубже разбираться в проблемах с полосой прокрутки и проблемах с шириной. –
using setVisible вместо добавления или удаления, вероятно, будет лучше ---> не имеет значения внутри JScrollPane, это мой вопрос к вам – mKorbel