Вопрос

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

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

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

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

Это было полезно?

Решение

Ваш вариант использования, кажется, идеально подходит для CardLayout .

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

Другие советы

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

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

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

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

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

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

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

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

Надеюсь, этот фрагмент кода даст вам представление об изменении 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);
        }
}

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

// вы должны сделать что-то вроде

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

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

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

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

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

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

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

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

Вам необходимо вызвать повторно проверить и перекрасить после добавления компонента до его появления в вашем контейнере.

Источник: http://docs.oracle.com/javase/ учебник / uiswing / макет / problems.html

У меня была точно такая же проблема !! 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 (), нет validate (), не требуется CardLayout.

    Ответ layout.replace () существует / работает только в GroupLayout Manager.

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

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

    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. Мой советую использовать оба варианта.

    Просто вызовите метод 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();
    ...
    

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

    layout.replace(existingComponent, newComponent)
    

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

    Лицензировано под: CC-BY-SA с атрибуция
    Не связан с StackOverflow
    scroll top