java swing GroupLayout - Как поменять положение компонентов
У меня есть JFrame, размещенный в GroupLayout. Я хотел бы поменять положение двух компонентов в этом JFrame, когда пользователь нажимает кнопку. Я использовал метод replace()
в GroupLayout, чтобы заменить один другим. Вот код, который я хочу поменять местами двумя кнопками: buttons[0]
а также buttons[1]
:
groupLayout.replace(buttons[1], buttons[2]);
groupLayout.replace(buttons[2], buttons[1]);
Однако программа теряет NullPointerException
когда я запускаю это. Исключение не дает никакой полезной информации:
Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException
at javax.swing.GroupLayout$ComponentInfo.setBounds(Unknown Source)
at javax.swing.GroupLayout.layoutContainer(Unknown Source)
at java.awt.Container.layout(Unknown Source)
at java.awt.Container.doLayout(Unknown Source)
at java.awt.Container.validateTree(Unknown Source)
at java.awt.Container.validateTree(Unknown Source)
at java.awt.Container.validateTree(Unknown Source)
at java.awt.Container.validate(Unknown Source)
at javax.swing.RepaintManager$2.run(Unknown Source)
at javax.swing.RepaintManager$2.run(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.ProtectionDomain$1.doIntersectionPrivilege(Unknown Source)
at javax.swing.RepaintManager.validateInvalidComponents(Unknown Source)
at javax.swing.RepaintManager$ProcessingRunnable.run(Unknown Source)
at java.awt.event.InvocationEvent.dispatch(Unknown Source)
at java.awt.EventQueue.dispatchEventImpl(Unknown Source)
at java.awt.EventQueue.access$200(Unknown Source)
at java.awt.EventQueue$3.run(Unknown Source)
at java.awt.EventQueue$3.run(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.ProtectionDomain$1.doIntersectionPrivilege(Unknown Source)
at java.awt.EventQueue.dispatchEvent(Unknown Source)
at java.awt.EventDispatchThread.pumpOneEventForFilters(Unknown Source)
at java.awt.EventDispatchThread.pumpEventsForFilter(Unknown Source)
at java.awt.EventDispatchThread.pumpEventsForHierarchy(Unknown Source)
at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
at java.awt.EventDispatchThread.run(Unknown Source)
(Сначала я думал, что это потому, что кнопки [2] уже были удалены. Но когда я пытался replace(buttons[1],buttons[3])
где кнопки [3] не были добавлены в groupLayout раньше, ничего не пошло не так. Поэтому я до сих пор не могу понять, что случилось.)
Затем мне пришла в голову идея сохранить ссылку на группу, которая содержит только тот компонент, который я хочу изменить, чтобы манипулировать им позже. Вот мой код:
if(count % 2 == 1) {
groupLayout.replace(buttons[1], buttons[2]);
button2HorizontalGroup.addComponent(buttons[1]);
button2VerticalGroup.addComponent(buttons[1]);
}else {
groupLayout.replace(buttons[2], buttons[1]);
button2HorizontalGroup.addComponent(buttons[2]);
button2VerticalGroup.addComponent(buttons[2]);
}
Но это может быть скорее взломом, чем решением. Кроме того, было бы обременительно, если бы кто-то обменивался большим количеством компонентов. Есть ли лучшее решение для обмена компонентов в GroupLayout? (Решения в других макетах также приветствуются:))
Благодарю.
Обновить:
@ user1803551: Вот мой код (GroupLayoutTest - это класс, расширяющий JFrame):
public GroupLayoutTest() {
// Allow group layout to automatically creat the gap between components and containers.
groupLayout.setAutoCreateGaps(true);
groupLayout.setAutoCreateContainerGaps(true);
setLayout(groupLayout);
buttons = new JButton[4];
buttons[0] = new JButton("small 1");
buttons[1] = new JButton("medium 2");
buttons[2] = new JButton("big 3");
buttons[1].addActionListener(replaceHandler);
buttons[2].addActionListener(replaceHandler);
button1HorizontalGroup.addComponent(buttons[1]);
button1VerticalGroup.addComponent(buttons[1]);
button2HorizontalGroup.addComponent(buttons[2]);
button2VerticalGroup.addComponent(buttons[2]);
groupLayout.setHorizontalGroup(
groupLayout.createParallelGroup()
.addGroup(groupLayout.createSequentialGroup()
.addGap(39)
.addComponent(buttons[0])
// Make it like a Spring
.addPreferredGap(LayoutStyle.ComponentPlacement.RELATED, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addGap(10)
.addGroup(button1HorizontalGroup)
.addGap(52))
.addGroup(groupLayout.createSequentialGroup()
.addPreferredGap(LayoutStyle.ComponentPlacement.RELATED, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addGap(0)
.addGroup(button2HorizontalGroup)
.addContainerGap(GroupLayout.DEFAULT_SIZE, 160))
);
groupLayout.setVerticalGroup(
groupLayout.createSequentialGroup()
.addContainerGap(50, 50)
.addGroup(groupLayout.createParallelGroup()
.addComponent(buttons[0])
.addGroup(button1VerticalGroup) )
.addGap(10)
.addPreferredGap(LayoutStyle.ComponentPlacement.RELATED, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addGroup(button2VerticalGroup)
.addContainerGap(168, 168));
groupLayout.linkSize(SwingConstants.HORIZONTAL, buttons[1],buttons[2]);
pack();
setLocationRelativeTo(null);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
private class ReplaceHandler implements ActionListener {
private int count = 0;
@Override
public void actionPerformed(ActionEvent e) {
count += 1;
if(count % 2 == 1) {
groupLayout.replace(buttons[1], buttons[2]);
button2HorizontalGroup.addComponent(buttons[1]);
button2VerticalGroup.addComponent(buttons[1]);
}else {
groupLayout.replace(buttons[2], buttons[1]);
button2HorizontalGroup.addComponent(buttons[2]);
button2VerticalGroup.addComponent(buttons[2]);
}
groupLayout.linkSize(SwingConstants.HORIZONTAL, buttons[1],buttons[2]);
}
}
@camickr: Как видно из приведенного выше кода, я просто получаю удовольствие от своего первого опыта с GroupLayout. Мне бы хотелось, чтобы одна кнопка ("средняя" и "маленькая") заменяла друг друга, когда я нажимал на нее. В конце концов, спасибо за ваш совет.:)
1 ответ
Я просто получаю удовольствие от моего первого опыта GroupLayout.
Ну, вы должны сначала изучить другие менеджеры по расположению
Мне бы хотелось, чтобы одна кнопка ("средняя" и "маленькая") заменяла друг друга, когда я нажимал на нее.
Создайте JPanel для двух кнопок и добавьте панель в макет.
Сделайте одну кнопку видимой, а другую - невидимой. Когда вы нажимаете на кнопку, вы переключаете состояния видимости обеих кнопок.