JProgressbar width using Grid/FlowLayout

社会主义新天地 提交于 2020-01-03 13:00:29

问题


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

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

回答1:


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

    }
}



回答2:


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




回答3:


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:



来源:https://stackoverflow.com/questions/6802824/jprogressbar-width-using-grid-flowlayout

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!