【问题标题】:JProgressbar width using Grid/FlowLayout使用 Grid/FlowLayout 的 JProgressbar 宽度
【发布时间】:2011-07-23 19:35:42
【问题描述】:

我正在开发一个看起来像这样的下载器:

JFrame 使用 BorderLayout。 在北方,我有一个 JPanel(FlowLayout)。在南部还有一个 JPanel(FlowLayout),在西部我只有一个 JTextArea(在 JScrollPane 中)。这一切都正确显示。但是,在 EAST,我目前有一个 JPanel(GridLayout(10, 1))。

我想在 EAST 部分中显示最多 10 个 JProgressBar,它们是动态添加和从面板中删除的。问题是,我无法让它们看起来像我想要的那样:我希望 JProgressBars 的宽度填满整个 EAST 部分,因为 1)这使应用程序看起来更对称,并且 2)ProgressBars 可能包含目前不适合的长字符串。我尝试将包含 GridLayout(10, 1) 的 JPanel 放在一个流布局中,然后将该流布局放在 EAST 部分,但这也不起作用。

我的代码(SSCCE)目前如下:

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

    }
}

提前致谢。

编辑

最简单的解决方案:改变

add(ProgressBarPanel, BorderLayout.EAST);

add(ProgressBarPanel, BorderLayout.CENTER);

【问题讨论】:

    标签: java swing grid-layout flowlayoutpanel border-layout


    【解决方案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();
            }
    
        }
    }
    

    【讨论】:

    • 请使用通用命名法来命名属性和方法。那将是camelCase,而不是EachWordUpperCase
    • 感谢您的快速回答。但我只是(经过数小时的搜索,典型的)找到了解决我的问题的最简单方法。将 ProgressBarPanel 添加到 CENTER 而不是 EAST 得到我正在寻找的结果。 不尝试这样做感觉很愚蠢 你对命名约定是正确的。我会考虑到这一点。
    【解决方案2】:

    好吧。这可能,但在您的示例中,CENTER 区域占用了一些Rectangle,很难将CENTER 区域减少/删除为零Size

    向北 JPanel (BorderLayout) 放置另一个 JPanel 并将其放在 EAST (LayoutManager 将是 GridLayout(1,2,10,10))并在此处放置两个 JComponents JTextField - threadIdTextFieldJButton - downloadButton , 你需要setPreferredSize 1) JComponents (正确的方式) 或 2) 整个JPanel (可能的方式)

    JScrollPaneJTextArea 必须放在CENTER 区域

    JPanelJProgressBars 放置到 EAST,但再次将 PreferredSize 设置为与 JPanel 相同的 JTextFieldJButton 来自 NORTH

    SOUTH JPanel 保持不变

    【讨论】:

    • 很好地提及首选尺寸。虽然我采用了“选项 2”——可能的方式,而不是“选项 1”——正确的方式。 “不包括电池..” ;)
    • @Andrew Thompson 那么你一定希望 Jeanette 或 Rob 不在 :-)
    • @mKorbel:阿门,尤其是 kleopatra/Jeanette(虽然上帝知道我尊重她的能力无与伦比)!
    • @mKorbel 嘿,先生,我不想惹麻烦。请不要告诉他们。 ;)
    【解决方案3】:

    请发布一个可编译的可运行小程序以获得最快的最佳帮助,SSCCE

    建议包括使用 GridLayout(0, 1)(行数可变,一列),或在使用扩展 JProgressBar 的自定义渲染器的 JList 中显示 JProgressBar。

    编辑 1:
    我知道 Andrew 已经发布了接受的答案(并且 1+ 是一个很好的答案),但我只是想证明这可以通过 JList 轻松完成,如下所示:

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

    这导致 GUI 看起来像这样:

    【讨论】:

    • 和(@Andrew Thompson)谁告诉过这里不是很有趣 +1
    猜你喜欢
    • 1970-01-01
    • 2011-10-08
    • 1970-01-01
    • 2019-09-12
    • 2011-09-09
    • 1970-01-01
    • 1970-01-01
    • 2015-01-08
    • 2019-05-16
    相关资源
    最近更新 更多