#java #swing
#java #swing
Вопрос:
Я хочу иметь возможность устанавливать область содержимого JFrame после нажатия кнопки внутри одной из JPanels этого фрейма.
Моя архитектура состоит из контроллера, который создает JFrame и первую JPanel внутри него. Из первой JPanel я вызываю метод: setcontentpane (JPanel jpanel) на контроллере. Однако вместо загрузки переданной JPanel она ничего не делает, кроме удаления всех панелей (см. Код ниже)
ActionListener внутри первой JPanel:
public void actionPerformed(ActionEvent arg0) {
controller.setpanel(new CustomPanel(string1, string2));
}
Контроллер:
JFrame frame;
public void setpanel(JPanel panel)
{
frame.getContentPane().removeAll();
frame.getContentPane().add(panel);
frame.repaint();
}
public Controller(JFrame frame)
{
this.frame=frame;
}
Кто-нибудь может сказать мне, что я делаю не так? Спасибо 🙂
Ответ №1:
Вызовите повторную проверку, затем перерисуйте. Это указывает менеджерам компоновки выполнять свои макеты своих компонентов:
JPanel contentPane = (JPanel) frame.getContentPane();
contentPane.removeAll();
contentPane.add(panel);
contentPane.revalidate();
contentPane.repaint();
Однако, если вы просто хотите поменять JPanels местами, лучше использовать CardLayout и поручить ему выполнять грязную работу.
Комментарии:
1. Полный угрей: Спасибо, я думаю, что буду использовать CardLayout. Мне все еще трудно понять, почему мой код не сработал.
2. @Джулиан, что значит, ты не понимаешь, почему твой код не сработал? Вы не вызывали метод revalidate(). Если вы имеете в виду, что не понимаете, зачем нужна revalidate (), тогда подумайте, что произойдет, если вы добавите 100 компонентов на панель? Не имеет смысла размещать компоненты после каждого оператора add (…) или remove (…). Таким образом, вместо этого вы сообщаете менеджеру макета, когда вы закончите вносить изменения, используя метод revalidate(). Тогда компоновка выполняется только один раз.
Ответ №2:
Я нашел способ сделать то, что я описал выше.
Реализация метода setpanel следующим образом:
public void setpanel(JPanel panel)
{
frame.setContentPane(panel);
frame.validate();
}
в моем случае это сработало.
Я уверен, что мне все еще нужно что-то исправить в моем коде, поскольку pack () по-прежнему сжимает окно, но, по крайней мере, метод, описанный выше, работает.
Ответ №3:
Всякий раз, когда вы меняете иерархию содержимого фрейма, вы должны вызвать pack()
.
Из документов:
Приводит к изменению размера этого окна в соответствии с предпочтительным размером и макетами его подкомпонентов. […] Окно будет проверено после вычисления предпочтительного размера.
Комментарии:
1. Выполнение этого просто приводит к уменьшению фрейма до минимально возможного размера. Возможно ли, что моя переданная JPanel по какой-то причине недоступна из метода? Я проверил, что вызывается конструктор переданной панели.
2. @Julian: Нет, JPanel, скорее всего, находится в JFrame. Более вероятно, что ваши предпочтительные размеры не были установлены или вы неправильно используете менеджеры компоновки.
3. Где обычно неправильно используются менеджеры компоновки? До сих пор я не обращал на них особого внимания.
4. @Julian: тогда в этом и проблема — обратите на них внимание и используйте их. Руководства по их использованию довольно приличные.