#java #swing #jframe #jpanel
#java #swing #jframe #jpanel
Вопрос:
На данный момент только для целей тестирования я хотел бы менять JPanel в JFrame каждый раз, когда на него нажимают. Я перебираю 3 панели / страницы, каждая из которых имеет свой уникальный цвет фона.
В настоящее время он изменится, но будет отображаться только тогда, когда дело доходит до самой первой добавленной панели, в противном случае отображается серый цвет по умолчанию.
Код:
@Override
public void mouseClicked(MouseEvent e) {
mainFrame.changePage();
}
public void changePage() {
if(currentPage != null) {
this.remove(currentPage);
}
currentPage = pages[pageNumber];
this.add(currentPage);
currentPage.setPage();
super.repaint();
pageNumber ;
if(pageNumber > 2) {
pageNumber = 0;
}
}
Комментарии:
1. Используйте a
CardLayout
для замены панелей. Прочитайте раздел из руководства по Swing о том, как использовать CardLayout для получения дополнительной информации и примеров, которые помогут вам начать.
Ответ №1:
Кроме комментария от @camickr для использования CardLayout
, вам необходимо revalidate
. Изменение:
super.repaint();
Для
revalidate();
Комментарии:
1. И причина, по которой вам нужен revalidate(), заключается в том, что диспетчер компоновки устанавливает только размер / расположение исходной панели, которую вы отображаете. Когда вы меняете местами панели, вам нужен метод revalidate() для вызова диспетчера компоновки, чтобы теперь текущей панели можно было присвоить размер / местоположение. Или вместо этого вы можете использовать API, чтобы не изобретать велосипед. CardLayout делает все это за вас, поэтому вам не нужно беспокоиться об этом.
2. Я не понимаю, почему это еще не было отмечено как принятый ответ
3. @nix_s Спасибо, теперь он работает с revalidate()! — это может решить проблему, но это не должно быть решением, которое вы используете. Научитесь использовать Swing так, как он был разработан, и не изобретайте велосипед. Вы все еще не подтвердили, что прочитали
CardLayout
в попытке понять, почему его следует использовать.CardLayout
Even поддерживает функцию «next», поэтому вам даже не нужно отслеживать, на какой панели вы находитесь. Если вы правильно используете API, у вас будет меньше проблем в будущем.4. Понятно. Теперь я попытаюсь реализовать CardLayout и вернусь, если у меня возникнут какие-либо проблемы. Большое вам спасибо.
Ответ №2:
РЕДАКТИРОВАТЬ: поскольку @camickr упомянул, что мой приведенный ниже код не соответствует рекомендациям, пожалуйста, обратитесь к следующей ссылке о том, как использовать CardLayout.
Как использовать CardLayout — учебные пособия по Java
просто для целей тестирования
Делая акцент на вышесказанном, вот несколько примеров кода. Это НЕ производственный класс, просто POC без необходимости использования CardLayout, упомянутого @camickr.
import java.awt.Color;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.*;
public class FirstSwingExample {
public static void main(String[] args) {
Swinger s = new Swinger();
}
}
class Swinger implements ActionListener {
int currFrame = 1;
JFrame f;
JLabel lblPanelOne, lblPanelTwo, lblPanelThree;
JPanel panelOne, panelTwo, panelThree;
JButton b;
public Swinger() {
setup();
}
private void setup() {
f=new JFrame();
panelOne = new JPanel();
lblPanelOne = new JLabel("Panel One");
panelOne.setBounds(0,0,100, 40);
panelOne.setBackground(Color.BLACK);
panelOne.add(lblPanelOne);
panelTwo = new JPanel();
lblPanelTwo = new JLabel("Panel Two");
panelTwo.setBounds(0,0,100, 40);
panelTwo.setBackground(Color.BLUE);
panelTwo.add(lblPanelTwo);
panelThree = new JPanel();
lblPanelThree = new JLabel("Panel Three");
panelThree.setBounds(0,0,100, 40);
panelThree.setBackground(Color.GREEN);
panelThree.add(lblPanelThree);
b=new JButton("Panel Two");
b.setBounds(130,100,100, 40);
b.setActionCommand("click");
b.addActionListener(this);
panelOne.setVisible(true);
f.add(panelOne);
f.add(b);
f.setSize(400,500);
f.setLayout(null);
f.setVisible(true);
}
@Override
public void actionPerformed(ActionEvent e) {
System.out.println(e.getActionCommand());
if(e.getActionCommand().equals("click")) {
switch(currFrame) {
case 1:
panelOne.setVisible(false);
f.remove(panelOne);
panelTwo.setVisible(true);
f.add(panelTwo);
b.setText("Panel Three");
currFrame ;
break;
case 2:
panelTwo.setVisible(false);
f.remove(panelTwo);
f.add(panelThree);
panelThree.setVisible(true);
b.setText("Panel One");
currFrame ;
break;
default:
panelThree.setVisible(false);
f.remove(panelThree);
f.add(panelOne);
panelOne.setVisible(true);
b.setText("Panel Two");
currFrame = 1;
break;
}
}
}
}
Комментарии:
1. (1-) Swing был разработан для использования с менеджерами компоновки. Не используйте нулевой макет. Не используйте setBounds() . Не изобретайте велосипед. Не используйте оператор switch для замены панелей. Что делать, если у вас 10 панелей?? Код становится беспорядочным и не поддерживается. Научитесь использовать существующие API, чтобы код был простым и удобным в обслуживании.
2. @camickr Я уже разъяснил в самом начале, что это было просто доказательство концепции. Пожалуйста, прочитайте мой ответ полностью. Я был бы признателен, если бы вы могли отозвать понижающий голос.
3. Это плохой ответ по причинам, указанным в моем комментарии. Я никому не рекомендую следовать этому подходу к решению проблемы.