Pregunta

Estoy trabajando en un descargador que se ve así en este momento:

Screenshot

El Jframe usa un BorderLayout. En el norte, tengo un JPanel (FlowLayout). En el sur también hay un JPanel (FlowLayout), en Occidente solo tengo un JTextarea (en un JScrollpane). Todo esto se muestra correctamente. Sin embargo, en el este actualmente tengo un JPanel (GridLayout (10, 1)).

Quiero mostrar hasta 10 jarras de J -Progress en la sección Este que se agregan y se eliminan del panel dinámicamente. El problema es que no puedo hacer que parezcan que quiero que se vean: quiero que el ancho de JProgressbars llene toda la sección este porque 1) esto le da a la aplicación un aspecto más simétrico y 2) las barras de progreso pueden contener cadenas largas que no encajan en este momento. He intentado poner el jpanel que contiene el GridLayout (10, 1) en un flujo de flujo y luego poner ese flujo de flujo en la sección Este, pero eso tampoco funcionó.

Mi código (SSCCE) es actualmente el siguiente:

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

    }
}

Gracias por adelantado.

EDITAR

Solución más fácil: cambiar

add(ProgressBarPanel, BorderLayout.EAST);

a

add(ProgressBarPanel, BorderLayout.CENTER);
¿Fue útil?

Solución

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

    }
}

Otros consejos

bien. Eso es posible, pero en tu ejemplo CENTER área ocupó algunos Rectangle, es difícil de reducir/eliminar CENTER área a la cero Size

Al norte JPanel (BorderLayout) Coloque otro JPanel y ponerlo al este (con LayoutManager sería GridLayout(1,2,10,10)) y ponte aquí dos JComponents JTextField - threadIdTextField y JButton - downloadButton, ahí eres necesario setPreferredSize 1) para JComponents (forma correcta) o 2) para todo JPanel (también posible de manera)

JScrollPane con JTextArea debe colocarse al CENTER área

JPanel con JProgressBars lugar para EAST, pero de nuevo configurado lo mismo PreferredSize como para JPanel con JTextField y JButton desde el NORTH

SOUTH JPanel permanece sin cambios

Publique un pequeño programa compilable ejecutable para obtener la mejor ayuda más rápida, un SSCCE.

Las sugerencias incluyen el uso de GridLayout (0, 1) (número variable de filas, una columna), o muestran las barras jProgress en una JLIST que utiliza un renderizador personalizado que extiende JProgressBar.

Editar 1:
Sé que Andrew ya ha publicado la respuesta aceptada (y 1+ para una excelente respuesta), pero solo quería demostrar que esto se puede hacer fácilmente con una Jlist, algo así:

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


}

Esto da como resultado una GUI como así:
enter image description here

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top