Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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);
like image 651
Matthias Avatar asked Jul 23 '11 19:07

Matthias


3 Answers

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();
        }

    }
}
like image 127
Andrew Thompson Avatar answered Oct 22 '22 04:10

Andrew Thompson


well. that possible, but in your example CENTER area occupated some Rectangle, its hard to reduce/remove CENTER area to the zero Size

to the North JPanel (BorderLayout) place another JPanel and put it to the EAST (with LayoutManager would be GridLayout(1,2,10,10)) and put here two JComponents JTextField - threadIdTextField and JButton - downloadButton, there you are needed setPreferredSize 1) for JComponents (correct way) or 2) for whole JPanel (possible way too)

JScrollPane with JTextArea must be placed to the CENTER area

JPanel with JProgressBars place to EAST, but again set same PreferredSize as for JPanel with JTextField and JButton from the NORTH

SOUTH JPanel remains without changes

like image 43
mKorbel Avatar answered Oct 22 '22 05:10

mKorbel


Please post a compilable runnable small program for the quickest best help, an SSCCE.

Suggestions include using GridLayout(0, 1) (variable number of rows, one column), or display the JProgressBars in a JList that uses a custom renderer that extends JProgressBar.

Edit 1:
I know that Andrew has already posted the accepted answer (and 1+ for an excellent answer), but I just wanted to demonstrate that this can be done readily with a JList, something like so:

import java.awt.*;
import java.awt.event.*;
import java.beans.*;
import java.util.Random;
import javax.swing.*;

public class EastProgressList extends JPanel {
   private DefaultListModel myListModel = new DefaultListModel();
   private JList myList = new JList(myListModel);
   private JTextField downloadUrlField = new JTextField(10);

   public EastProgressList() {
      JButton downLoadBtn = new JButton("Download");
      downLoadBtn.addActionListener(new ActionListener() {
         @Override
         public void actionPerformed(ActionEvent e) {
            downloadAction();
         }
      });
      JPanel northPanel = new JPanel();
      northPanel.add(new JLabel("File to Download:"));
      northPanel.add(downloadUrlField);
      northPanel.add(Box.createHorizontalStrut(15));
      northPanel.add(downLoadBtn);

      myList.setCellRenderer(new ProgressBarCellRenderer());
      JScrollPane eastSPane = new JScrollPane(myList);
      eastSPane.setPreferredSize(new Dimension(200, 100));

      setLayout(new BorderLayout());

      add(new JScrollPane(new JTextArea(20, 30)), BorderLayout.CENTER);
      add(northPanel, BorderLayout.NORTH);
      add(eastSPane, BorderLayout.EAST);
   }

   private void downloadAction() {
      String downloadUrl = downloadUrlField.getText();
      final MyData myData = new MyData(downloadUrl);
      myListModel.addElement(myData);
      myData.addPropertyChangeListener(new PropertyChangeListener() {
         public void propertyChange(PropertyChangeEvent evt) {
            if (evt.getPropertyName().equals(MyData.VALUE)) {
               myList.repaint();
               if (myData.getValue() >= 100) {
                  myListModel.removeElement(myData);
               }
            }
         }

      });
   }

   private class ProgressBarCellRenderer extends JProgressBar implements ListCellRenderer {
      protected ProgressBarCellRenderer() {
         setBorder(BorderFactory.createLineBorder(Color.blue));
      }

      public Component getListCellRendererComponent(JList list, Object value,
               int index, boolean isSelected, boolean cellHasFocus) {
         //setText(value.toString());
         MyData myData = (MyData)value;
         setValue(myData.getValue());
         setString(myData.getText());
         setStringPainted(true);
         return this;
      }
   }

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

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

class MyData {
   public static final int TIMER_DELAY = 300;
   public static final String VALUE = "value";
   protected static final int MAX_DELTA_VALUE = 5;
   private String text;
   private int value = 0;
   private Random random = new Random();
   private PropertyChangeSupport pcSupport = new PropertyChangeSupport(this);

   public MyData(String text) {
      this.text = text;
      new Timer(TIMER_DELAY, new ActionListener() {
         @Override
         public void actionPerformed(ActionEvent e) {
            int deltaValue = random.nextInt(MAX_DELTA_VALUE);
            int newValue = value + deltaValue;
            if (newValue >= 100) {
               newValue = 100;
               ((Timer)e.getSource()).stop();
            }
            setValue(newValue);
         }
      }).start();
   }

   public String getText() {
      return text;
   }

   public int getValue() {
      return value;
   }

   public void setValue(int value) {
      int oldValue = this.value;
      this.value = value;

      PropertyChangeEvent pcEvent = new PropertyChangeEvent(this, VALUE, oldValue, value);
      pcSupport.firePropertyChange(pcEvent);
   }

   public void addPropertyChangeListener(PropertyChangeListener pcListener) {
      pcSupport.addPropertyChangeListener(pcListener);
   }


}

This results in a GUI looking like so:
enter image description here

like image 3
Hovercraft Full Of Eels Avatar answered Oct 22 '22 04:10

Hovercraft Full Of Eels