Search code examples
javaswinglayout-managergrid-layoutcardlayout

GridLayout Contents not showing


I have a Jpanel which will display components in two views. Grid View and Card View.

The Card View is working fine . But when gridView is chosen the components are not displayed.

enter image description here

MCVE

SourceContainer.java

import java.awt.BorderLayout;
import java.awt.CardLayout;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.List;
import javax.swing.Box.Filler;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JToolBar;

public class SourceContainer extends JPanel implements ActionListener {

    JPanel sourceMainPanel;

    SourceCardPanel sourceCardPanel;
    SourceGridPanel sourceGridPanel;

    List<JComponent> components;

    Boolean cardView = true;

    public SourceContainer() {
        init();
        components = new ArrayList<>();
    }

    private void init() {
        setLayout(new BorderLayout());
        loadTitleComp();
        loadBodyPanel();
    }

    private void loadTitleComp() {
        JToolBar toolBar = new JToolBar();
        toolBar.setFloatable(false);
        toolBar.add(new Filler(new Dimension(), new Dimension(), new Dimension(10000, 10000)));
        toolBar.add(new Filler(new Dimension(35, 0), new Dimension(35, 0), new Dimension(10000, 10000)));

        JLabel label = new JLabel("Source");
        label.setFont(label.getFont().deriveFont(Font.BOLD, 14));
        toolBar.add(label);

        toolBar.add(new Filler(new Dimension(), new Dimension(), new Dimension(10000, 10000)));

        JButton button = new JButton("Switch");
        button.setActionCommand("SwitchView");
        button.addActionListener(this);
        toolBar.add(button);
        add(toolBar, BorderLayout.NORTH);
    }

    private void loadBodyPanel() {
        sourceMainPanel = new JPanel(new CardLayout());

        sourceCardPanel = new SourceCardPanel();
        sourceGridPanel = new SourceGridPanel();

        sourceMainPanel.add(sourceCardPanel, "Card");
        sourceMainPanel.add(sourceGridPanel, "Grid");

        add(sourceMainPanel, BorderLayout.CENTER);
    }

    public void addSourceComp(String name, JComponent comp) {
        JScrollPane scrollPane = new JScrollPane(comp);
        scrollPane.setName(name);
        components.add(scrollPane);
    }

    public void load() {
        switchView();
    }

    @Override
    public void actionPerformed(ActionEvent ae) {
        switch (ae.getActionCommand()) {
            case "SwitchView":
                cardView = !cardView;
                switchView();
                break;
            default:
                throw new UnsupportedOperationException();
        }
    }

    private void switchView() {
        CardLayout layout = (CardLayout) sourceMainPanel.getLayout();
        String cardName;
        if (cardView) {
            cardName = "Card";
            sourceCardPanel.loadCards();
        } else {
            sourceGridPanel.loadGrid();
            cardName = "Grid";
        }
        layout.show(sourceMainPanel, cardName);
    }

    class SourceCardPanel extends JPanel implements ActionListener {

        JPanel sourcePanel;
        CardLayout cardLayout;

        JLabel sourceLabel;

        public SourceCardPanel() {
            setLayout(new BorderLayout());
            cardLayout = new CardLayout();
            sourcePanel = new JPanel(cardLayout);
            sourceLabel = new JLabel("Soruce Project");
            init();
        }

        private void init() {
            JToolBar toolBar = new JToolBar();
            toolBar.setFloatable(false);

            toolBar.add(new Filler(new Dimension(), new Dimension(), new Dimension(10000, 10000)));

            JButton lbutton = new JButton("<<<");
//                    IconUtils.getIconByResourceName("goPrevious"));
            lbutton.setActionCommand("GoToLeft");
            lbutton.addActionListener(this);
            toolBar.add(lbutton);

            toolBar.add(sourceLabel);

            JButton rbutton = new JButton(">>>");
//                    IconUtils.getIconByResourceName("goNext"));
            rbutton.setActionCommand("GoToRight");
            rbutton.addActionListener(this);
            toolBar.add(rbutton);

            toolBar.add(new Filler(new Dimension(), new Dimension(), new Dimension(10000, 10000)));

            add(toolBar, BorderLayout.NORTH);
            add(sourcePanel, BorderLayout.CENTER);
        }

        public void addCard(JComponent comp) {
            sourcePanel.add(comp, comp.getName());
        }

        private JComponent getCurrentCard() {
            for (Component comp : sourcePanel.getComponents()) {
                if (comp.isVisible()) {
                    return (JComponent) comp;
                }
            }
            return null;
        }

        public void loadCards() {
            sourcePanel.removeAll();
            for (JComponent component : components) {
                addCard(component);
            }
            sourceLabel.setText(components.get(0).getName());
        }

        @Override
        public void actionPerformed(ActionEvent ae) {
            switch (ae.getActionCommand()) {
                case "GoToLeft":
                    cardLayout.previous(sourcePanel);
                    break;
                case "GoToRight":
                    cardLayout.next(sourcePanel);
                    break;
            }
            sourceLabel.setText(getCurrentCard().getName());
        }

    }

    class SourceGridPanel extends JPanel {

        JPanel gridpanel;

        public SourceGridPanel() {
            setLayout(new BorderLayout());
            gridpanel = new JPanel(new GridLayout());
            add(new JScrollPane(gridpanel), BorderLayout.CENTER);
        }

        public void loadGrid() {
            gridpanel.removeAll();
            for (int i = 0; i < components.size(); i++) {
                create(components.get(i), i);
            }
        }

        private void create(JComponent comp, int index) {
            JPanel panel = new JPanel(new BorderLayout());
            JToolBar toolBar = new JToolBar();
            toolBar.setFloatable(false);
            toolBar.add(new JLabel(comp.getName()));
            panel.add(toolBar, BorderLayout.NORTH);
            panel.add(comp, BorderLayout.CENTER);
            gridpanel.add(panel, index);
        }
    }
}

Test.java

import java.awt.BorderLayout;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.JFrame;
import javax.swing.JTree;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import merge.container.SourceContainer;

public class Test extends JFrame {

    public Test() {
        init();
    }

    private void init() {
        SourceContainer sc = new SourceContainer();
        for (int i = 0; i < 5; i++) {
            sc.addSourceComp("Sample " + i, new JTree(new Object[]{i}));
        }
        sc.load();
        add(sc, BorderLayout.CENTER);
    }

    public static void main(String[] args) {
        setUpUI("Nimbus");
        SwingUtilities.invokeLater(new Runnable() {

            @Override
            public void run() {
                Test samp = new Test();
                samp.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                samp.setTitle("Tree Test");
                samp.setSize(600, 500);
                samp.setLocationRelativeTo(null);
                samp.setVisible(true);
            }
        });
    }

    private static void setUpUI(String ui) {
        try {
            for (UIManager.LookAndFeelInfo info : UIManager.getInstalledLookAndFeels()) {
                if (ui.equals(info.getName())) {
                    UIManager.setLookAndFeel(info.getClassName());
                    break;
                }
            }
        } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
            Logger.getLogger(Test.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

}

Solution

  • in loadGrid() change your loop to:

    for (int i = 0; i < components.size(); i++) {
        create(components.get(i), i);
        components.get(i).setVisible(true);
    }
    

    EDIT: I realized I had offered a solution without actually offering a complete answer, so for the sake of completeness:

    CardLayout shows 1 component at a time by modifying the visibility of the components it manages. The documentation states this, although it doesn't really emphasize it (it uses terms like "Flip" in most of the document):

    https://docs.oracle.com/javase/8/docs/api/java/awt/CardLayout.html

    Java 8 - CardLayout

    Only one card is visible at a time, and the container acts as a stack of cards. The first component added to a CardLayout object is the visible component when the container is first displayed.

    Here is an example showing this behavior:

    public static void main(String[] args){
        ArrayList<JComponent> components = new ArrayList<>();
        components.add(new JPanel());
        components.add(new JPanel());
        components.add(new JPanel());
        
        System.out.println("Component Visibility Prior to Card Layout:");
        showVisibilityStatus(components);
        
        JPanel cardPane = new JPanel(new CardLayout());
        for (JComponent component : components){
            cardPane.add(component);
        }
        
        System.out.println("\nComponent Visibility After Card Layout:");
        showVisibilityStatus(components);
    }
    
    public static void showVisibilityStatus(ArrayList<JComponent> components){
        for (JComponent component : components){
            System.out.println(component.isVisible());
        }
    }
    

    The console output of which is:

    Component Visibility Prior to Card Layout:
    true
    true
    true
    
    Component Visibility After Card Layout:
    true
    false
    false
    

    So when moving components that have been placed in a panel using a CardLayout into another panel using a different layout (such as GridLayout), the visibility of those components may need to be explicitly set.