views:

36

answers:

1

Hi guys

My question relates to swing programming. I want to enlarge a component (component x) by removing it from its parent panel (component a) and adding it in one of component a's parent (component b). Before that, I call setVisible(false) on all components in b. After that I want to make this back by removing it from b and adding on a.

After that all components are not longer resizable.

Why that?

An easy example:

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();
    }
}
+1  A: 

After that all components are not longer resizable.

I think the choice of LayoutManager obscures the effect. In general, it's a good idea to build your GUI on the event dispatch thread, and it's a bad idea to block that thread using sleep(). This alternative example uses javax.swing.Timer to change the contents periodically in the timer's actionPerformed() method.

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;
    }
}
trashgod
Of course, this thread which performs the change is a replacement for an user interaction (double click on a tab). Nevertheless using a timer is better.I've forgotten to mention that you can replace this missing ViewPanel class with a JPanel.
Junior Software Developer