2016-06-24 4 views
0

Я пытаюсь создать графический интерфейс с использованием Swing на Java, который выполняет следующие действия:Как динамически добавлять элементы в JScrollPanel?

При нажатии кнопки «Добавить» создается JPanel и заполняет всю ширину графического интерфейса. Внутри JPanel будут созданы JLabels, используя FlowLayout, которые сообщают конкретные данные (например, имя, идентификатор пользователя и т. Д.). Когда бы ни была нажата кнопка «Добавить», я хочу, чтобы новый JPanel добавлялся прямо под предыдущим, так что JScrollPane при необходимости активирует свою вертикальную полосу прокрутки. В принципе, я хочу, чтобы JScrollPane мог динамически добавлять новые JPanels внутри него.

Однако у меня было несколько проблем, пытающихся это сделать. Я не могу понять, какой LayoutManager использовать для панели в JScrollPane. Я попытался использовать GridlLayout, но это не работает, потому что, когда есть достаточно JPanels, чтобы скрыть весь JScrollPane, GridLayout просто создает новый столбец, который хлюпает в новых JPanels вместо добавления его ниже предыдущего JPanel. Что я должен сделать для этого? Вот некоторые изображения того, что у меня есть, и пример того, что я хочу.

GUI

Вот что я хочу, чтобы это произошло:

GUI Example

Любая помощь будет принята с благодарностью, спасибо заранее! :)

EDIT: Вот пример моего кода, который я пробовал с помощью GridLayout.

public Window() { 


    setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
    setBounds(100, 100, 701, 400); 
    contentPane = new JPanel(); 
    contentPane.setBorder(new EmptyBorder(5, 5, 5, 5)); 
    contentPane.setLayout(new BorderLayout(0, 0)); 
    setContentPane(contentPane); 

    JPanel buttonPanel = new JPanel(); 
    contentPane.add(buttonPanel, BorderLayout.SOUTH); 

    JButton btnAdd = new JButton("Add"); 
    buttonPanel.add(btnAdd); 

    JScrollPane scrollPane = new JScrollPane(); 
    contentPane.add(scrollPane, BorderLayout.CENTER); 

    JPanel systemsPanel = new JPanel(); 
    scrollPane.setViewportView(systemsPanel); 
    systemsPanel.setLayout(new GridLayout(8, 1, 0, 0)); //8 rows for now 



    for (int i = 1; i < 50; i++) { 
     systemsPanel.add(new JButton("test"), "cell 0 " + i); 
    } 
    Dimension dim = Toolkit.getDefaultToolkit().getScreenSize(); 
    this.setLocation(dim.width/2 - this.getSize().width/2, dim.height/2 - this.getSize().height/2); //Center the Frame 

} 
+2

Пожалуйста, создать и оставить в силе [mcve] для лучший шанс быстро получить наилучшую помощь. Этот код был бы небольшим, самостоятельным и размещался здесь как текст с отформатированным кодом с вашим вопросом, а не по ссылке. Удачи! –

+3

И GridLayout должен работать нормально, но вы, вероятно, не используете его правильно. Опять же, покажите нам, как вы используете его в своем коде. Кроме того, вы уверены, что не хотите использовать JTable? –

+0

Вы ошибаетесь. Это покажет нам, что вы делаете неправильно, и какие предположения у вас есть, которые неверны. Опять же, пожалуйста, покажите нам соответствующий код. И, пожалуйста, пройдите раздел [help], особенно подраздел о том, как задавать вопросы на этом сайте. –

ответ

2

Если вы хотите добавить строки JPanel, в GUI, я бы поместить их в JPanel, который использует GridLayout (0, 1), или (0, 1, х, у). Значение 0 означает переменное количество строк, 1 для 1 столбца, x и y - вертикальный и горизонтальный зазор. Затем я помещал это в BorderLayout - используя JPanel в позицию NORTH, чтобы строки не расширялись, чтобы заполнить видовое окно scrollpane, как они в противном случае хотели бы сделать. Я поместил бы эту вторую упаковку JPanel в окно просмотра JScrollPane.

После добавления каких-либо компонентов я бы назвал revalidate и repaint в контейнере, чтобы его менеджеры по макетам активировали и правильно размещали новые компоненты, а также перерисовку, чтобы избавиться от любых грязных пикселей, которые могут витаться (что гораздо важнее, когда удаление компонентов).

Например, мой MCVE:

import java.awt.BorderLayout; 
import java.awt.Color; 
import java.awt.Dimension; 
import java.awt.GridLayout; 
import java.awt.event.ActionEvent; 

import javax.swing.*; 

public class AddRowA extends JPanel { 
    private static final int PREF_W = 650; 
    private static final int PREF_H = 400; 

    // JPanel to hold all rows. uses gridlayout that has 1 column and variable number 
    // of rows 
    private JPanel rowHolderPanel = new JPanel(new GridLayout(0, 1, 1, 1)); 

    public AddRowA() { 
     // outerPanel is a wrapper or container JPanel that is 
     // held by JScrollPane's viewport that holds the rowHolderPanel in 
     // a BorderLayout.PAGE_START location, so the rows don't expand unnecessarily 
     JPanel outerPanel = new JPanel(new BorderLayout()); 
     outerPanel.add(rowHolderPanel, BorderLayout.PAGE_START); 
     JScrollPane scrollPane = new JScrollPane(outerPanel); 
     scrollPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS); 

     JPanel addPanel = new JPanel(); 
     addPanel.add(new JButton(new AddAction("Add"))); 

     setLayout(new BorderLayout()); 
     add(scrollPane, BorderLayout.CENTER); 
     add(addPanel, BorderLayout.PAGE_END); 
    } 

    @Override 
    public Dimension getPreferredSize() { 
     if (isPreferredSizeSet()) { 
      return super.getPreferredSize(); 
     } 
     return new Dimension(PREF_W, PREF_H); 
    } 

    private class AddAction extends AbstractAction { 
     public AddAction(String name) { 
      super(name); 
      int mnemonic = (int) name.charAt(0); 
      putValue(MNEMONIC_KEY, mnemonic); 
     } 

     @Override 
     public void actionPerformed(ActionEvent e) { 
      JPanel panel = new JPanel(); 
      panel.add(new JLabel("Foo")); 
      panel.add(Box.createHorizontalStrut(25)); 
      panel.add(new JButton("Bar")); 
      panel.setBorder(BorderFactory.createLineBorder(Color.BLACK, 3)); 

      rowHolderPanel.add(panel); 
      rowHolderPanel.revalidate(); 
      rowHolderPanel.repaint(); 
     } 
    } 

    private static void createAndShowGui() { 
     JFrame frame = new JFrame("Add Row A"); 
     frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     frame.getContentPane().add(new AddRowA()); 
     frame.pack(); 
     frame.setLocationRelativeTo(null); 
     frame.setVisible(true); 
    } 

    public static void main(String[] args) { 
     SwingUtilities.invokeLater(() -> createAndShowGui()); 
    } 
} 

Но тогда, вы лучше использовать JTable ... например:

import java.awt.BorderLayout; 
import java.awt.event.ActionEvent; 
import javax.swing.*; 
import javax.swing.table.DefaultTableModel; 

public class AddRowB extends JPanel { 
    private MyTableModel tableModel = new MyTableModel(); 
    private JTable table = new JTable(tableModel); 

    public AddRowB() { 
     JPanel addPanel = new JPanel(); 
     addPanel.add(new JButton(new AddAction("Add"))); 

     setLayout(new BorderLayout()); 
     add(new JScrollPane(table)); 
     add(addPanel, BorderLayout.PAGE_END); 
    } 

    private class AddAction extends AbstractAction { 
     public AddAction(String name) { 
      super(name); 
      int mnemonic = (int) name.charAt(0); 
      putValue(MNEMONIC_KEY, mnemonic); 
     } 

     @Override 
     public void actionPerformed(ActionEvent e) { 
      RowData row = new RowData("Type", "Address", "User ID"); 
      tableModel.addRow(row); 
     } 
    } 

    private static void createAndShowGui() { 
     JFrame frame = new JFrame("Add Row B"); 
     frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     frame.getContentPane().add(new AddRowB()); 
     frame.pack(); 
     frame.setLocationRelativeTo(null); 
     frame.setVisible(true); 
    } 

    public static void main(String[] args) { 
     SwingUtilities.invokeLater(() -> createAndShowGui()); 
    } 
} 

class MyTableModel extends DefaultTableModel { 
    private static final String[] COLUMNS = {"Type", "Address", "User ID"}; 

    public MyTableModel() { 
     super(COLUMNS, 0); 
    } 

    public void addRow(RowData rowData) { 
     Object[] row = { 
       rowData.getType(), 
       rowData.getAddress(), 
       rowData.getUserID() 
     }; 
     addRow(row); 
    } 
} 

class RowData { 
    String type; 
    String address; 
    String userID; 

    public RowData(String type, String address, String userID) { 
     this.type = type; 
     this.address = address; 
     this.userID = userID; 
    } 

    public String getType() { 
     return type; 
    } 

    public String getAddress() { 
     return address; 
    } 

    public String getUserID() { 
     return userID; 
    } 

} 
+0

Очень информативный пост, спасибо! – 0Calories

Смежные вопросы