Динамическое удаление компонента из JPanel

Вот исполняемый фрагмент кода, объясняющий проблему -

Я могу удалить s1 и s2, но не s3.
Это не похоже на MigLayout (я его использую), так как я вижу такое же поведение и с макетом по умолчанию.


import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;

import javax.swing.BorderFactory;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;

import net.miginfocom.swing.MigLayout;

public class MyFrame2 extends JFrame {
    private JPanel main;
    private JPanel s1;
    private JPanel s2;
    private JPanel s3;

    public static void main(String[] args) throws InterruptedException {
        MyFrame2 f = new MyFrame2();
        f.setVisible(true);
        Thread.sleep(2000); //you can see all three panels for two seconds

        f.main.remove(f.s1);
        f.main.validate();
        Thread.sleep(2000);
        f.main.remove(f.s2);
        f.main.validate();
        Thread.sleep(2000);
        f.main.remove(f.s3);
        f.main.validate();
    }

    public MyFrame2() {
        main = new JPanel();

        main.setLayout(new MigLayout());

        main.add(new JLabel("Why does s3 not disappear?"),"w 200, h 100, wrap");

        s1 = new JPanel();
        s1.setBorder(BorderFactory.createTitledBorder(BorderFactory.createLineBorder(Color.GRAY,1),"s1"));
        main.add(s1,"w 90%, h 300, wrap");

        s2 = new JPanel();
        s2.setBorder(BorderFactory.createTitledBorder(BorderFactory.createLineBorder(Color.GRAY,1),"s2"));
        main.add(s2,"w 90%, h 300, wrap");

        s3 = new JPanel();
        s3.setBorder(BorderFactory.createTitledBorder(BorderFactory.createLineBorder(Color.GRAY,1),"s3"));
        main.add(s3,"w 90%, h 300, wrap");

        getContentPane().setLayout(new BorderLayout());
        getContentPane().add(main, BorderLayout.CENTER);

        setSize(new Dimension(800, 600));

    }
}


person Amol Katdare    schedule 07.02.2012    source источник


Ответы (2)


Вызов в конце, после последнего f.validate():

f.repaint(50L);

Поскольку последняя проверка не меняет макет.

person Joop Eggen    schedule 07.02.2012
comment
Спасибо. Оно работает! (+1). не могли бы вы немного уточнить? Почему последняя проверка не меняет макет, в то время как все предыдущие проверки делают это? (Очевидно, что я не особо разрабатываю свинг!) - person Amol Katdare; 07.02.2012
comment
Последняя проверка действительно изменяет макет — вы просто этого не видите. Последний компонент фактически был удален после вызова проверки, но вам нужно перекрасить компонент, чтобы увидеть визуальное доказательство этого удаления. - person Hovercraft Full Of Eels; 07.02.2012
comment
Спасибо на воздушной подушке (+1). Почему перерисовка не требуется для отражения визуальных изменений при более ранних удалениях (s1 и s2)? - person Amol Katdare; 07.02.2012

Во-первых, объекты Swing GUI должны создаваться и управляться только на поток отправки событий, но вы не должны спать на EDT. Вместо этого используйте javax.swing.Timer, чтобы отметить время, как показано здесь.

person trashgod    schedule 07.02.2012
comment
@amol: родственные компоненты были затронуты, изменены размеры, и их пришлось перерисовывать при проверке. Последний компонент не вызывал такой перерисовки. (извините, неправильное место этого комментария) - person Joop Eggen; 07.02.2012