Компоненты больше не могут быть изменены после перемещения

Мой вопрос касается свинг-программирования. Я хочу увеличить компонент (компонент x), удалив его из его родительской панели (компонент a) и добавив его в один из родительских компонентов компонента a (компонент b). Перед этим я вызываю setVisible (false) для всех компонентов в b. После этого я хочу вернуть это обратно, удалив его из b и добавив a.

После этого размер всех компонентов больше нельзя будет изменить.

Почему так?

Простой пример:

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JTabbedPane;

public class SwingTest {

    private static ViewPanel layer1;
    private static JFrame frame;
    private static JTabbedPane tabbedPane;
    private static ViewPanel root;

    public static void main(String[] args) {
        frame = new JFrame();
        frame.setLayout(new BorderLayout());
        frame.setMinimumSize(new Dimension(800, 600));

        root = new ViewPanel();
        root.setBackground(Color.blue);
        root.setPreferredSize(new Dimension(400, 600));
        root.setLayout(new BorderLayout());
        root.add(new JLabel("blue area"));

        layer1 = new ViewPanel();
        layer1.setBackground(Color.red);
        layer1.setPreferredSize(new Dimension(400, 600));
        layer1.setLayout(new BorderLayout());

        tabbedPane = new JTabbedPane();
        tabbedPane.add("A", new JLabel("A label"));
        tabbedPane.setPreferredSize(new Dimension(400, 600));

        layer1.add(tabbedPane);

        root.add(layer1);
        frame.add(root, BorderLayout.NORTH);
        frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
        frame.pack();
        frame.setVisible(true);

        Thread t = new Thread() {

            @Override
            public void run() {
                try {
                    Thread.sleep(8000);
                    System.out.println("start");
                    for (Component c : root.getComponents()) {
                        c.setVisible(false);
                    }
                    layer1.remove(tabbedPane);
                    root.add(tabbedPane);

                    Thread.sleep(8000);

                    root.remove(tabbedPane);
                    layer1.add(tabbedPane);

                    for (Component c : root.getComponents()) {
                        c.setVisible(true);
                        c.repaint();
                    }
                } catch (InterruptedException e) {
                    //...
                }
            }
        };
        t.start();
    }
}

person DME    schedule 15.06.2010    source источник
comment
Переформатированный код; пожалуйста, вернитесь, если неверно; ViewPanel отсутствует.   -  person trashgod    schedule 16.06.2010


Ответы (1)


После этого размер всех компонентов больше нельзя изменить.

Я думаю, что выбор LayoutManager затемняет эффект. Как правило, рекомендуется создавать свой графический интерфейс на основе события поток отправки, и блокировать этот поток с помощью sleep() - плохая идея. В этом альтернативном примере javax.swing.Timer используется для периодического изменения содержимого в методе actionPerformed() таймера.

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTabbedPane;
import javax.swing.Timer;

public class SwingTest implements ActionListener, Runnable {

    private JFrame frame;
    private ViewPanel root;
    private ViewPanel layer1;
    private JTabbedPane tabbedPane;
    private Timer t = new Timer(1000, this);
    private boolean remove = true;

    public static void main(String[] args) {
        EventQueue.invokeLater(new SwingTest());
    }

    private static class ViewPanel extends JPanel {

        public ViewPanel(Color color) { // default FlowLayout
            this.setPreferredSize(new Dimension(400, 500));
            this.setBackground(color);
        }
    }

    @Override
    public void run() {
        frame = new JFrame(); // default BorderLayout
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setPreferredSize(new Dimension(600, 600));
        root = new ViewPanel(Color.blue);
        root.add(new JLabel("Blue area"));
        layer1 = new ViewPanel(Color.red);
        tabbedPane = new JTabbedPane();
        tabbedPane.add("A", new JLabel("A label", JLabel.CENTER));
        tabbedPane.setPreferredSize(root.getPreferredSize());
        layer1.add(tabbedPane);
        root.add(layer1);
        root.add(new JLabel("Blue area"));
        frame.add(root, BorderLayout.CENTER);
        frame.pack();
        frame.setVisible(true);
        t.start();
    }

    @Override
    public void actionPerformed(ActionEvent e) {
        if (remove) {
            for (Component c : root.getComponents()) {
                c.setVisible(false);
            }
            layer1.remove(tabbedPane);
        } else {
            layer1.add(tabbedPane);
            for (Component c : root.getComponents()) {
                c.setVisible(true);
            }
        }
        remove = !remove;
    }
}
person trashgod    schedule 15.06.2010
comment
Конечно, этот поток, который выполняет изменение, является заменой взаимодействия с пользователем (двойной щелчок по вкладке). Тем не менее, лучше использовать таймер. Я забыл упомянуть, что вы можете заменить этот отсутствующий класс ViewPanel на JPanel. - person DME; 16.06.2010