Search code examples
javaswinggrid-layoutflowlayoutpanelborder-layout

JProgressbar width using Grid/FlowLayout


I'm working on a downloader which looks like this at the moment:

Screenshot

The JFrame uses a BorderLayout. In the NORTH, I have a JPanel(FlowLayout). In the SOUTH there is also a JPanel(FlowLayout), in the WEST I just have a JTextArea (in a JScrollPane). This is all shown correctly. However, in the EAST I currently have a JPanel(GridLayout(10, 1)).

I want to show up to 10 JProgressBars in the EAST section which are added and removed from the panel dynamically. The problem is, I can not get them to look like I want to them to look: I want the JProgressBars' width to fill up the entire EAST section because 1) This gives the app a more symmetrical look and 2) The ProgressBars may contain long strings that don't fit at the moment. I've tried putting the JPanel that contains the GridLayout(10, 1) in a flowlayout and then put that flowlayout in the EAST section, but that didn't work either.

My code (SSCCE) is currently as follows:

import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.HashMap;
import java.util.Map;

public class Main {

    public static void main(String[] args) {
        new DownloadFrame();
    }

    private static class DownloadFrame extends JFrame {

        private JButton downloadButton;
        private JTextField threadIdTextField;
        private JTextArea downloadStatusTextArea;
        private JScrollPane scrollPane;
        private JTextField downloadLocationTextField;
        private JButton downloadLocationButton;

        private JPanel North;
        private JPanel South;
        private JPanel ProgressBarPanel;

        private Map<String, JProgressBar> progressBarMap;

        public DownloadFrame() {
            InitComponents();
            InitLayout();
            AddComponents();
            AddActionListeners();

            setVisible(true);
            setSize(700, 300);
        }

        private void InitComponents() {
            downloadButton = new JButton("Dowload");
            threadIdTextField = new JTextField(6);
            downloadStatusTextArea = new JTextArea(10, 30);
            scrollPane = new JScrollPane(downloadStatusTextArea, ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED, ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
            downloadLocationTextField = new JTextField(40);
            downloadLocationButton = new JButton("...");
            North = new JPanel();
            South = new JPanel();
            ProgressBarPanel = new JPanel();
            progressBarMap = new HashMap<String, JProgressBar>();
        }

        private void InitLayout() {
            North.setLayout(new FlowLayout());
            South.setLayout(new FlowLayout());
            ProgressBarPanel.setLayout(new GridLayout(10, 1));
        }

        private void AddComponents() {
            North.add(threadIdTextField);
            North.add(downloadButton);
            add(North, BorderLayout.NORTH);

            add(ProgressBarPanel, BorderLayout.EAST);

            South.add(downloadLocationTextField);
            South.add(downloadLocationButton);
            add(South, BorderLayout.SOUTH);

            add(scrollPane, BorderLayout.WEST);
        }

        private void AddActionListeners() {
            downloadButton.addActionListener(new ActionListener() {
                public void actionPerformed(ActionEvent e) {
                    addNewProgessBar(threadIdTextField.getText());
                }
            });
        }

        public void addNewProgessBar(String threadId) {
            JProgressBar progressBar = new JProgressBar();
            progressBar.setStringPainted(true);
            progressBarMap.put(threadId, progressBar);
            drawProgessBars();
        }

        void drawProgessBars() {
            ProgressBarPanel.removeAll();
            for (JProgressBar progressBar : progressBarMap.values()) {
                ProgressBarPanel.add(progressBar);
            }
            validate();
            repaint();
        }

    }
}

Thanks in advance.

EDIT

Easiest solution: change

add(ProgressBarPanel, BorderLayout.EAST);

to

add(ProgressBarPanel, BorderLayout.CENTER);

Solution

  • Screenshot of GUI

    import javax.swing.*;
    import javax.swing.border.*;
    import java.awt.*;
    import java.awt.event.ActionEvent;
    import java.awt.event.ActionListener;
    import java.util.HashMap;
    import java.util.Map;
    
    public class Main {
    
        public static void main(String[] args) {
            new DownloadFrame();
        }
    
        private static class DownloadFrame extends JFrame {
    
            private JButton downloadButton;
            private JTextField threadIdTextField;
            private JTextArea downloadStatusTextArea;
            private JScrollPane scrollPane;
            private JTextField downloadLocationTextField;
            private JButton downloadLocationButton;
    
            private JPanel North;
            private JPanel South;
            private JPanel ProgressBarPanel;
    
            private Map<String, JProgressBar> progressBarMap;
    
            public DownloadFrame() {
                InitComponents();
                AddComponents();
                AddActionListeners();
    
                pack();
                setVisible(true);
                //setSize(700, 300);
            }
    
            private void InitComponents() {
                setLayout(new BorderLayout());
                downloadButton = new JButton("Dowload");
                threadIdTextField = new JTextField(6);
                downloadStatusTextArea = new JTextArea(10, 30);
                scrollPane = new JScrollPane(downloadStatusTextArea, ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED, ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
                downloadLocationTextField = new JTextField(40);
                downloadLocationButton = new JButton("...");
                North = new JPanel(new FlowLayout());
                South = new JPanel(new FlowLayout());
                ProgressBarPanel = new JPanel(new GridLayout(0, 1));
                ProgressBarPanel.setBorder(new LineBorder(Color.black));
                ProgressBarPanel.setPreferredSize(new Dimension(300,20));
                progressBarMap = new HashMap<String, JProgressBar>();
            }
    
            private void AddComponents() {
                North.add(threadIdTextField);
                North.add(downloadButton);
                add(North, BorderLayout.NORTH);
    
                add(ProgressBarPanel, BorderLayout.EAST);
    
                South.add(downloadLocationTextField);
                South.add(downloadLocationButton);
                add(South, BorderLayout.SOUTH);
    
                add(scrollPane, BorderLayout.WEST);
            }
    
            private void AddActionListeners() {
                downloadButton.addActionListener(new ActionListener() {
                    public void actionPerformed(ActionEvent e) {
                        addNewProgessBar(threadIdTextField.getText());
                    }
                });
            }
    
            public void addNewProgessBar(String threadId) {
                JProgressBar progressBar = new JProgressBar();
                progressBar.setStringPainted(true);
                progressBarMap.put(threadId, progressBar);
                drawProgessBars();
            }
    
            void drawProgessBars() {
                ProgressBarPanel.removeAll();
                for (JProgressBar progressBar : progressBarMap.values()) {
                    ProgressBarPanel.add(progressBar);
                }
                validate();
                repaint();
            }
    
        }
    }