javaswingjframelayout-managergrouplayout

How to recreate this progress bar based JFrame?


I'm wanting to create a JFrame and I just found the perfect frame. I want to recreate this:

enter image description here

The code to get this frame looks like this:

progressBar = new JProgressBar();
statusLbl = new JLabel();
statusLbl1 = new JLabel();
percentLbl = new JLabel();

setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
setTitle("Auto-Updater");
addWindowListener(new WindowAdapter() {
    public void windowClosing(WindowEvent evt) {
    formWindowClosing(evt);
    }
});
statusLbl.setText("Status:");
statusLbl1.setText("N/A");
percentLbl.setText("0%");
GroupLayout layout = new GroupLayout(getContentPane());
getContentPane().setLayout(layout);

layout.setHorizontalGroup(layout.createParallelGroup(GroupLayout.Alignment.LEADING).addGroup(
    layout.createSequentialGroup()
    .addContainerGap()
    .addGroup(layout.createParallelGroup(GroupLayout.Alignment.LEADING)
        .addGroup(layout.createSequentialGroup()
            .addComponent(statusLbl).addPreferredGap(LayoutStyle.ComponentPlacement.RELATED)
            .addComponent(statusLbl1).addPreferredGap(LayoutStyle.ComponentPlacement.RELATED, 304, 32767)
            .addComponent(percentLbl)).addComponent(progressBar, GroupLayout.Alignment.TRAILING, -1, 380, 32767))
    .addContainerGap()));

layout.setVerticalGroup(layout.createParallelGroup(GroupLayout.Alignment.LEADING).addGroup(
    layout.createSequentialGroup()
    .addContainerGap()
    .addGroup(layout.createParallelGroup(GroupLayout.Alignment.LEADING, false)
        .addGroup(layout.createParallelGroup(GroupLayout.Alignment.BASELINE)
            .addComponent(statusLbl1, -1, -1, 32767)
            .addComponent(percentLbl))
        .addComponent(statusLbl, -1, -1, 32767)).addPreferredGap(LayoutStyle.ComponentPlacement.RELATED)
    .addComponent(progressBar, -2, 30, -2).addContainerGap(-1, 32767)));

pack();

But I think this looks ugly and has zero readability, so I'm asking you: How can I recreate this frame using a different layout or how can I use this layout differently to make it readable?


Solution

  • If the progress string could be included within the progress bar it would be done with a single JPanel with a BorderLayout. Put the label in the PAGE_START and the progress bar in CENTER (which is the default if no constraint is specified).

    Note: I'd tend to display that panel in a JDialog or a JOptionPane rather than a JFrame, but here is a frame based version.

    enter image description here

    import java.awt.*;
    import javax.swing.*;
    import javax.swing.border.EmptyBorder;
    
    public class ProgressBarPanel {
    
        private JComponent ui = null;
    
        ProgressBarPanel() {
            initUI();
        }
    
        public void initUI() {
            if (ui!=null) return;
    
            ui = new JPanel(new BorderLayout(4,4));
            ui.setBorder(new EmptyBorder(4,4,4,4));
    
            JProgressBar progressBar = new JProgressBar(0, 100) {
                public Dimension getPreferredSize() {
                    // base this on a multiple of the default preferred size to
                    // account for the size of the font used to paint the 
                    // progress string
                    return new Dimension(400,40);
                }
            };
            progressBar.setValue(50);
            progressBar.setStringPainted(true);
            ui.add(progressBar);
    
            ui.add(new JLabel("Status: N/A"), BorderLayout.PAGE_START);
        }
    
        public JComponent getUI() {
            return ui;
        }
    
        public static void main(String[] args) {
            Runnable r = new Runnable() {
                @Override
                public void run() {
                    try {
                        UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                    } catch (Exception useDefault) {
                    }
                    ProgressBarPanel o = new ProgressBarPanel();
    
                    JFrame f = new JFrame(o.getClass().getSimpleName());
                    f.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
                    f.setLocationByPlatform(true);
    
                    f.setContentPane(o.getUI());
                    f.pack();
                    f.setMinimumSize(f.getSize());
    
                    f.setVisible(true);
                }
            };
            SwingUtilities.invokeLater(r);
        }
    }