简体   繁体   中英

JProgressBar not taking up space when not visible

I want to be able to hide a JProgressBar and have the panel it resides in not change size.

Currently, when I set the progress bar to visible (via pb.setVisible(true) ), I get a layout like the following:

进度条可见

Then when I set it to not visible, I get the following layout:

进度条不可见

  • Apparently forcing the JPanel to be a specific size doesn't help.
  • Setting an explicit size on the JProgressBar doesn't appear to help.
  • Monkeying with the vertical gaps in NetBean's GUI editor didn't appear to help (I made it fixed size).

I think I'm missing something easy here, and I can't see what it is.

How do I force a hidden JProgressBar to still take up real estate in the form (especially vertical real estate)?

Code is below, for what it's worth. I'm much more interested in the concept that I've missed than the specifics of the code. :-)

package pbtest;

public class MyFrame extends javax.swing.JFrame {

public MyFrame() {
    initComponents();
}

/**
 * This method is called from within the constructor to initialize the form.
 * WARNING: Do NOT modify this code. The content of this method is always
 * regenerated by the Form Editor.
 */
@SuppressWarnings("unchecked")
// <editor-fold defaultstate="collapsed" desc="Generated Code">                          
private void initComponents() {

    jPanel1 = new javax.swing.JPanel();
    pb = new javax.swing.JProgressBar();
    bnVis = new javax.swing.JButton();
    bnInvis = new javax.swing.JButton();
    jButton1 = new javax.swing.JButton();

    setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);

    jPanel1.setBorder(javax.swing.BorderFactory.createEtchedBorder());

    bnVis.setText("Visible");
    bnVis.addActionListener(new java.awt.event.ActionListener() {
        public void actionPerformed(java.awt.event.ActionEvent evt) {
            bnVisActionPerformed(evt);
        }
    });

    bnInvis.setText("Not Visible");
    bnInvis.addActionListener(new java.awt.event.ActionListener() {
        public void actionPerformed(java.awt.event.ActionEvent evt) {
            bnInvisActionPerformed(evt);
        }
    });

    jButton1.setText("Some Other Random Component");

    javax.swing.GroupLayout jPanel1Layout = new javax.swing.GroupLayout(jPanel1);
    jPanel1.setLayout(jPanel1Layout);
    jPanel1Layout.setHorizontalGroup(
        jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
        .addGroup(jPanel1Layout.createSequentialGroup()
            .addGap(19, 19, 19)
            .addComponent(pb, javax.swing.GroupLayout.PREFERRED_SIZE, 217, javax.swing.GroupLayout.PREFERRED_SIZE)
            .addContainerGap(45, Short.MAX_VALUE))
        .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, jPanel1Layout.createSequentialGroup()
            .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
            .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, jPanel1Layout.createSequentialGroup()
                    .addComponent(bnVis)
                    .addGap(28, 28, 28)
                    .addComponent(bnInvis)
                    .addGap(47, 47, 47))
                .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, jPanel1Layout.createSequentialGroup()
                    .addComponent(jButton1)
                    .addGap(30, 30, 30))))
    );
    jPanel1Layout.setVerticalGroup(
        jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
        .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, jPanel1Layout.createSequentialGroup()
            .addContainerGap(20, Short.MAX_VALUE)
            .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                .addComponent(bnInvis)
                .addComponent(bnVis))
            .addGap(4, 4, 4)
            .addComponent(pb, javax.swing.GroupLayout.PREFERRED_SIZE, 35, javax.swing.GroupLayout.PREFERRED_SIZE)
            .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
            .addComponent(jButton1))
    );

    javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
    getContentPane().setLayout(layout);
    layout.setHorizontalGroup(
        layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
        .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
            .addContainerGap(22, Short.MAX_VALUE)
            .addComponent(jPanel1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
            .addContainerGap())
    );
    layout.setVerticalGroup(
        layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
        .addGroup(layout.createSequentialGroup()
            .addContainerGap()
            .addComponent(jPanel1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
            .addContainerGap(64, Short.MAX_VALUE))
    );

    pack();
}// </editor-fold>                        

private void bnVisActionPerformed(java.awt.event.ActionEvent evt) {                                      
   pb.setVisible(true);
}                                     

private void bnInvisActionPerformed(java.awt.event.ActionEvent evt) {                                        
    pb.setVisible(false);
}                                       

public static void main(String args[]) {
    java.awt.EventQueue.invokeLater(new Runnable() {
        public void run() {
            new MyFrame().setVisible(true);
        }
    });
}

// Variables declaration - do not modify                     
private javax.swing.JButton bnInvis;
private javax.swing.JButton bnVis;
private javax.swing.JButton jButton1;
private javax.swing.JPanel jPanel1;
private javax.swing.JProgressBar pb;
// End of variables declaration                   

}

Option: place it in a JPanel that swaps the view in and out using a CardLayout. You could swap it say with an empty JLabel. The CardLayout -using JPanel will size at the largest dimension necessary to show all swapped components. Then add the CardLayout-using JPanel at the location of where you want to display the JProgressBar.

Using your code as an example (although I hate GroupLayout):

import java.awt.CardLayout;
import javax.swing.JLabel;
import javax.swing.JPanel;

@SuppressWarnings("serial")
public class MyFrame extends javax.swing.JFrame {

    private static final String PROGRESS_BAR = "progress bar";
    private static final String EMPTY = "empty";
    public MyFrame() {
        initComponents();
    }

    private void initComponents() {

        jPanel1 = new javax.swing.JPanel();
        pb = new javax.swing.JProgressBar();
        bnVis = new javax.swing.JButton();
        bnInvis = new javax.swing.JButton();
        jButton1 = new javax.swing.JButton();

        //!!
        cardLayout = new CardLayout();
        cardHolderPanel = new JPanel(cardLayout);
        cardHolderPanel.add(pb, PROGRESS_BAR);
        cardHolderPanel.add(new JLabel(), EMPTY);

        setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);

        jPanel1.setBorder(javax.swing.BorderFactory.createEtchedBorder());

        bnVis.setText("Visible");
        bnVis.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                bnVisActionPerformed(evt);
            }
        });

        bnInvis.setText("Not Visible");
        bnInvis.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                bnInvisActionPerformed(evt);
            }
        });

        jButton1.setText("Some Other Random Component");

        javax.swing.GroupLayout jPanel1Layout = new javax.swing.GroupLayout(jPanel1);
        jPanel1.setLayout(jPanel1Layout);
        jPanel1Layout.setHorizontalGroup(jPanel1Layout
                .createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                .addGroup(
                        jPanel1Layout
                                .createSequentialGroup()
                                .addGap(19, 19, 19)
                                .addComponent(cardHolderPanel, javax.swing.GroupLayout.PREFERRED_SIZE, 217,
                                        javax.swing.GroupLayout.PREFERRED_SIZE).addContainerGap(45, Short.MAX_VALUE))
                .addGroup(
                        javax.swing.GroupLayout.Alignment.TRAILING,
                        jPanel1Layout
                                .createSequentialGroup()
                                .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                                .addGroup(
                                        jPanel1Layout
                                                .createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                                                .addGroup(
                                                        javax.swing.GroupLayout.Alignment.TRAILING,
                                                        jPanel1Layout.createSequentialGroup().addComponent(bnVis)
                                                                .addGap(28, 28, 28).addComponent(bnInvis)
                                                                .addGap(47, 47, 47))
                                                .addGroup(
                                                        javax.swing.GroupLayout.Alignment.TRAILING,
                                                        jPanel1Layout.createSequentialGroup().addComponent(jButton1)
                                                                .addGap(30, 30, 30)))));
        jPanel1Layout.setVerticalGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                .addGroup(
                        javax.swing.GroupLayout.Alignment.TRAILING,
                        jPanel1Layout
                                .createSequentialGroup()
                                .addContainerGap(20, Short.MAX_VALUE)
                                .addGroup(
                                        jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                                                .addComponent(bnInvis).addComponent(bnVis))
                                .addGap(4, 4, 4)
                                .addComponent(cardHolderPanel, javax.swing.GroupLayout.PREFERRED_SIZE, 35,
                                        javax.swing.GroupLayout.PREFERRED_SIZE)
                                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                                .addComponent(jButton1)));

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
        getContentPane().setLayout(layout);
        layout.setHorizontalGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING).addGroup(
                javax.swing.GroupLayout.Alignment.TRAILING,
                layout.createSequentialGroup()
                        .addContainerGap(22, Short.MAX_VALUE)
                        .addComponent(jPanel1, javax.swing.GroupLayout.PREFERRED_SIZE,
                                javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                        .addContainerGap()));
        layout.setVerticalGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING).addGroup(
                layout.createSequentialGroup()
                        .addContainerGap()
                        .addComponent(jPanel1, javax.swing.GroupLayout.PREFERRED_SIZE,
                                javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                        .addContainerGap(64, Short.MAX_VALUE)));

        pack();
    }// </editor-fold>

    private void bnVisActionPerformed(java.awt.event.ActionEvent evt) {
        // pb.setVisible(true);
        cardLayout.show(cardHolderPanel, PROGRESS_BAR);
    }

    private void bnInvisActionPerformed(java.awt.event.ActionEvent evt) {
        // pb.setVisible(false);  // !!
        cardLayout.show(cardHolderPanel, EMPTY);;
    }

    public static void main(String args[]) {
        java.awt.EventQueue.invokeLater(new Runnable() {
            public void run() {
                new MyFrame().setVisible(true);
            }
        });
    }

    private javax.swing.JButton bnInvis;
    private javax.swing.JButton bnVis;
    private javax.swing.JButton jButton1;
    private javax.swing.JPanel jPanel1;
    private CardLayout cardLayout;
    private JPanel cardHolderPanel;
    private javax.swing.JProgressBar pb;
}

If this were my project, I'd consider creating a class just for this, say something called SwappingComponent, and it could look like so:

import java.awt.CardLayout;
import javax.swing.JComponent;
import javax.swing.JLabel;
import javax.swing.JPanel;

public @SuppressWarnings("serial")
class SwappingComponent extends JPanel {
    private static final String SHOW = "show";
    private static final String HIDE = "hide";
    JComponent component;
    CardLayout cardLayout = new CardLayout();

    public SwappingComponent(JComponent component) {
        setLayout(cardLayout);
        this.component = component;
        add(component, SHOW);
        add(new JLabel(), HIDE);
    }

    public JComponent getComponent() {
        return component;
    }

    public void showComponent(boolean show) {
        String key = show ? SHOW : HIDE;
        cardLayout.show(this, key);
    }

}

I could then use it like so:

import java.awt.BorderLayout;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.AbstractAction;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JProgressBar;
import javax.swing.SwingUtilities;
import javax.swing.Timer;
import javax.swing.border.Border;

@SuppressWarnings("serial")
public class MyGui2 extends JPanel {
    private JProgressBar progressBar = new JProgressBar(0, 100);
    private SwappingComponent swappingComponent = new SwappingComponent(progressBar);

    public MyGui2() {
        progressBar.setStringPainted(true);
        int delay = 100;
        new Timer(delay, new ActionListener() {
            private int value = 0;

            @Override
            public void actionPerformed(ActionEvent e) {
                progressBar.setValue(value);

                if (value >= 100) {
                    value = 0;
                } else {
                    value += 2;
                    value = Math.min(value, 100);
                }
            }
        }).start();
        JPanel northPanel = new JPanel(new GridLayout(1, 0, 5, 5));
        northPanel.add(new JButton(new ShowAction("Show")));
        northPanel.add(new JButton(new HideAction("Hide")));

        JPanel southPanel = new JPanel();
        southPanel.add(new JButton("Some Component"));

        Border outsideBorder = BorderFactory.createEmptyBorder(15, 15, 15, 15);
        Border insideBorder = BorderFactory.createEtchedBorder();
        Border border = BorderFactory.createCompoundBorder(outsideBorder, insideBorder);
        setBorder(border);
        setLayout(new BorderLayout(6, 6));
        add(swappingComponent, BorderLayout.CENTER);
        add(northPanel, BorderLayout.PAGE_START);
        add(southPanel, BorderLayout.PAGE_END);
    }

    private class ShowAction extends AbstractAction {
        public ShowAction(String name) {
            super(name);
            putValue(MNEMONIC_KEY, (int) name.charAt(0));
        }

        @Override
        public void actionPerformed(ActionEvent e) {
            swappingComponent.showComponent(true);
        }
    }

    private class HideAction extends AbstractAction {
        public HideAction(String name) {
            super(name);
            putValue(MNEMONIC_KEY, (int) name.charAt(0));
        }

        @Override
        public void actionPerformed(ActionEvent e) {
            swappingComponent.showComponent(false);
        }
    }

    private static void createAndShowGui() {
        JFrame frame = new JFrame("MyGui2");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.getContentPane().add(new MyGui2());
        frame.pack();
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                createAndShowGui();
            }
        });
    }

}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM