Подтвердить что ты не робот

Как сменить JPanel внутри JFrame на лету?

Проще говоря, есть простое приложение java swing, состоящее из JFrame с некоторыми компонентами в нем. Одним из компонентов является JPanel, который должен быть заменен другим JPanel на действие пользователя.

Итак, какой правильный способ сделать такое? Я пробовал

panel = new CustomJPanelWithComponentsOnIt();
parentFrameJPanelBelongsTo.pack();

но это не сработает. Что бы вы предложили?

4b9b3361

Ответ 1

Ваш прецедент, кажется идеальным для CardLayout.

В макете карты вы можете добавить несколько панелей в одном и том же месте, но затем показать или скрыть одну панель за раз.

Ответ 2

1) Настройка первой панели:

JFrame frame=new JFrame();
frame.getContentPane().add(new JPanel());

2) Замена панели:

frame.getContentPane().removeAll();
frame.getContentPane().add(new JPanel());

Также обратите внимание, что вы должны сделать это в потоке событий, чтобы обеспечить использование SwingUtilities.invokeLater или SwingWorker

Ответ 3

frame.setContentPane(newContents());
frame.revalidate(); // frame.pack() if you want to resize.

Помните, что Java использует передачу аргументов 'copy reference by value'. Таким образом, изменение переменной не изменит копии ссылки, переданной другим методам.

Также обратите внимание, что JFrame очень сбивает с толку имя юзабилити. Добавление компонента или настройка макета (обычно) выполняет операцию на панели содержимого. Как ни странно, получение макета действительно дает вам менеджер компоновки фреймов.

Ответ 4

Надеюсь, что этот фрагмент кода даст вам представление об изменении jPanels внутри JFrame.

public class PanelTest extends JFrame {

        Container contentPane;

        public PanelTest()  {
           super("Changing JPanel inside a JFrame");
           contentPane=getContentPane();
        }

        public void createChangePanel() {
           contentPane.removeAll();
           JPanel newPanel=new JPanel();
           contentPane.add(newPanel);
           System.out.println("new panel created");//for debugging purposes
           validate();
           setVisible(true);
        }
}

Ответ 5

В действии пользователя:

//вам нужно что-то делать по строкам

myJFrame.getContentPane().removeAll()
myJFrame.getContentPane().invalidate()

myJFrame.getContentPane().add(newContentPanel)
myJFrame.getContentPane().revalidate()

Затем вы можете изменить размер своего wndow по мере необходимости.

Ответ 6

Все зависит от того, как его использовать. Если вам нужно переключаться между этими двумя панелями, используйте CardLayout. Если вы только переключаетесь с первого на второй один раз (и не возвращаетесь назад), я бы использовал telcontar предложение и просто заменил его. Хотя если JPanel не единственная вещь в вашем фрейме, я бы использовал remove(java.awt.Component) вместо removeAll.

Если вы находитесь где-то между этими двумя случаями, это в основном компромисс между временным пространством. CardLayout сэкономит ваше время, но займет больше памяти, если вы будете постоянно держать эту всю панель в памяти. Но если вы просто заменяете панель, когда это необходимо, и создавайте ее по требованию, вам не нужно поддерживать этот круг, но требуется больше времени для переключения.

Также вы можете попробовать использовать JTabbedPane для использования вкладок (это даже проще, чем CardLayout, потому что оно автоматически обрабатывает отображение/скрытие)

Ответ 7

Другие люди ответили на вопрос. Я хочу предложить вам использовать JTabbedPane вместо замены содержимого. Как правило, плохо видеть, что визуальные элементы вашего приложения исчезают или заменяются другим контентом. Конечно, есть исключения для каждого правила, и только вы и ваше сообщество пользователей можете выбрать наилучший подход.

Ответ 8

У меня была такая же проблема!! Increadible!! Решение, которое я нашел, было:

  • Добавление всех компонентов (JPanels) в контейнер;
  • Использование метода setVisible (false) для всех из них;
  • В действии пользователя, установив setVisible (true) на панель, я хотел шоу.
// Hiding all components (JPanels) added to a container (ex: another JPanel)
for (Component component : this.container.getComponents()) {
      component.setVisible(false);
}
// Showing only the selected JPanel, the one user wants to see
panel.setVisible(true);

Нет revalidate(), no validate(), не требуется CardLayout.

Ответ 9

Ответ layout.replace() существует или работает только в диспетчере GroupLayout.

Другие LayoutManagers (CardLayout, BoxLayout и т.д.) НЕ поддерживают эту функцию, но требуют сначала RemoveLayoutComponent (а затем AddLayoutComponent (назад снова.:-) [Только установление прямой записи]

Ответ 10

Я предлагаю вам добавить обе панели при создании фрейма, а затем изменить видимую панель, вызвав setVisible (true/false) на обоих. При вызове setVisible родитель будет уведомлен и попросит перекрасить себя.

Ответ 11

class Frame1 extends javax.swing.JFrame {

    remove(previouspanel); //or getContentPane().removeAll();

    add(newpanel); //or setContentPane(newpanel);

    invalidate(); validate(); // or ((JComponent) getContentPane()).revalidate();

    repaint(); //DO NOT FORGET REPAINT

}

Иногда вы можете выполнять работу без использования повторной аттестации, а иногда и без использования repaint.My советуем использовать оба.

Ответ 12

Проблема. Мой компонент не появляется после добавления его в контейнер.

Вам нужно вызвать revalidate и repaint после добавления компонента , прежде чем он отобразит в вашем контейнере.

Источник: http://docs.oracle.com/javase/tutorial/uiswing/layout/problems.html

Ответ 13

Просто вызовите метод pack() после установки ContentPane, (java 1.7, может быть, старше), например:

JFrame frame = new JFrame();  
JPanel panel1 = new JPanel(); 
JPanel panel2 = new JPanel(); 
....
frame.setContentPane(panel1);
frame.pack();
...

frame.setContentPane(panel2);
frame.pack();
...

Ответ 14

вы можете использовать метод замены макета:

layout.replace(existingComponent, newComponent)

существующие и новые компоненты также могут быть JPanels.