2015-11-24 8 views
2

Я пытаюсь создать графический интерфейс в swing. GUI будет содержать переменное число JPanel s с фиксированной высотой, уложенной друг на друга. Когда общая высота JPanel s в стеке больше высоты охватывающей рамки, пользователь должен иметь возможность прокручивать вверх и вниз по панелям.Прокручиваемый список с элементами заданной высоты пикселей в Java Swing

  ____________________ 
     |     | 
     | panel 1   | 
     |     | 
     |____________________| 
     |     | 
     | panel 2   | 
     |     | 
     |____________________| 
    ___|____________________|___ 
    | | panel 3   | | 
    | |     | | 
    | |____________________| | ^
    | |     | |  | 
    | | panel 4   | |  | 
    | |     | |  | 
    | |____________________| |  v 
    | |     | | 
    | | panel 5   | | 
    |___|____________________|___| 
     |____________________| 
     |     | 
     | panel 6   | 
     |     | 
     |____________________| 

Я попытался с помощью комбинации JScrollPane с и JPanel с с GridLayout и GridBagLayout, а также призывы к setPreferedSize и setMinimumSize ни к какому успеху. Я чувствую, что установка такого рода gui должна быть довольно простой, но, похоже, не может найти решения.

+0

См. Править для ответа –

+0

'Я попытался использовать комбинацию JScrollPanes и JPanels с GridLayout и GridBagLayout, а также вызовы setPreferedSize и setMinimumSize без успеха.' - Не используйте вызовы 'setPreferredSize()' , Это предотвратит прокрутку от работы !!! Просто добавьте дочерние панели на родительскую панель и создайте JScrollPane с помощью родительской панели, а затем добавьте scrollPane в фрейм. – camickr

+0

См. Последние изменения, которые теперь показывают также решение JList. –

ответ

4

Если вы используете JPanels, то JPanel, который удерживается в окне просмотра, должен переопределять класс JPanel и должен реализовывать интерфейс Scrollable, возвращающий правильные значения для переопределенных методов, особенно метод getPreferredScrollableViewportSize(). Тем не менее, для моих денег я бы предпочел использовать JList и использовать соответствующие средства рендеринга вместо JPanels, а затем установить мои JLists visibleRowCount с помощью метода setVisibleRowCount(...).

Например:

Пример отредактированного сих пор показывают, как JList и прокруткой JPanel

import java.awt.Component; 
import java.awt.Dimension; 
import java.awt.GridBagConstraints; 
import java.awt.GridBagLayout; 
import java.awt.GridLayout; 
import java.awt.Insets; 
import java.awt.Rectangle; 
import javax.swing.*; 

@SuppressWarnings("serial") 
public class VisibleRows extends JPanel { 
    private DefaultListModel<Datum> dataModel = new DefaultListModel<>(); 
    private JList<Datum> datumList = new JList<>(dataModel); 

    public VisibleRows() { 
     DataPanel dataPanel = new DataPanel(8); 
     for (int i = 0; i < 200; i++) { 
      String name = "John Smith " + i; 
      int value = i; 
      Datum datum = new Datum(name, value); 
      dataPanel.addDatum(datum); 
      dataModel.addElement(datum); 
     } 

     JScrollPane scrollPane1 = new JScrollPane(dataPanel); 
     scrollPane1.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS); 

     add(scrollPane1); 

     datumList.setVisibleRowCount(8); 
     datumList.setCellRenderer(new DatumRenderer()); 
     datumList.setPrototypeCellValue(new Datum("XXXXXXXXXXX", 200)); 
     JScrollPane scrollPane2 = new JScrollPane(datumList); 
     scrollPane2.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS); 

     add(scrollPane2); 

    } 

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

    public static void main(String[] args) { 
     SwingUtilities.invokeLater(new Runnable() { 
      public void run() { 
       createAndShowGui(); 
      } 
     }); 
    } 
} 

@SuppressWarnings("serial") 
class DatumRenderer extends DatumPanel implements ListCellRenderer<Datum> { 

    @Override 
    public Component getListCellRendererComponent(JList<? extends Datum> list, Datum value, int index, 
      boolean isSelected, boolean cellHasFocus) { 
     setDatum(value); 
     return this; 
    } 

} 

@SuppressWarnings("serial") 
class DataPanel extends JPanel implements Scrollable { 
    private int visibleRowCount = 1; 

    public DataPanel(int visibleRowCount) { 
     this.visibleRowCount = visibleRowCount; 
     setLayout(new GridLayout(0, 1)); 
    } 

    public void addDatum(Datum datum) { 
     add(new DatumPanel(datum)); 
    } 

    @Override 
    public Dimension getPreferredScrollableViewportSize() { 
     if (getComponentCount() > 0) { 
      JComponent comp = (JComponent) getComponents()[0]; 
      int width = getPreferredSize().width; 
      int height = visibleRowCount * comp.getPreferredSize().height; 
      Dimension d = new Dimension(width, height); 
      System.out.println(d); 
      return d; 
     } else { 
      return new Dimension(0, 0); 
     } 
    } 

    @Override 
    public int getScrollableUnitIncrement(Rectangle visibleRect, int orientation, int direction) { 
     if (getComponentCount() > 0) { 
      JComponent comp = (JComponent) getComponents()[0]; 
      Dimension d = comp.getPreferredSize(); 
      if (orientation == SwingConstants.VERTICAL) { 
       return d.height; 
      } else { 
       return d.width; 
      } 
     } 
     return 0; 
    } 

    @Override 
    public int getScrollableBlockIncrement(Rectangle visibleRect, int orientation, int direction) { 
     if (getComponentCount() > 0) { 
      JComponent comp = (JComponent) getComponents()[0]; 
      Dimension d = comp.getPreferredSize(); 
      if (orientation == SwingConstants.VERTICAL) { 
       return visibleRowCount * d.height; 
      } else { 
       return d.width; 
      } 
     } 
     return 0; 
    } 

    @Override 
    public boolean getScrollableTracksViewportWidth() { 
     return true; 
    } 

    @Override 
    public boolean getScrollableTracksViewportHeight() { 
     return false; 
    } 

} 

@SuppressWarnings("serial") 
class DatumPanel extends JPanel { 
    private static final int GBC_I = 3; 
    private Datum datum; 
    private JLabel nameLabel = new JLabel(); 
    private JLabel valueLabel = new JLabel(); 

    public DatumPanel() { 
     setLayout(new GridBagLayout()); 
     add(new JLabel("Name:"), createGbc(0, 0)); 
     add(nameLabel, createGbc(1, 0)); 
     add(new JLabel("Value:"), createGbc(0, 1)); 
     add(valueLabel, createGbc(1, 1)); 
    } 

    public DatumPanel(Datum datum) { 
     this(); 
     setDatum(datum); 
    } 

    public final void setDatum(Datum datum) { 
     this.datum = datum; 
     nameLabel.setText(datum.getName()); 
     valueLabel.setText("" + datum.getValue()); 
    } 

    public Datum getDatum() { 
     return datum; 
    } 

    private GridBagConstraints createGbc(int x, int y) { 
     GridBagConstraints gbc = new GridBagConstraints(); 
     gbc.gridx = x; 
     gbc.gridy = y; 
     gbc.insets = new Insets(GBC_I, GBC_I, GBC_I, GBC_I); 
     gbc.insets.left = x != 0 ? 3 * GBC_I : GBC_I; 
     gbc.weightx = 0.0; 
     gbc.weighty = 0.0; 
     return gbc; 
    } 
} 

class Datum { 
    private String name; 
    private int value; 

    public Datum(String name, int value) { 
     this.name = name; 
     this.value = value; 
    } 

    public String getName() { 
     return name; 
    } 

    public int getValue() { 
     return value; 
    } 

    @Override 
    public String toString() { 
     StringBuilder sb = new StringBuilder(); 
     sb.append("Name: " + name + "\n"); 
     sb.append("Value: " + value); 
     return super.toString(); 
    } 

} 
0
import javax.swing.*; 

public class ButtonsInScrollPane{ 

    public static void main(String[] args){ 
     JFrame frame = new JFrame(); 
     JPanel p = new JPanel(); 
     p.setLayout(new BoxLayout(p, BoxLayout.PAGE_AXIS)); 
     p.add(getJButton(p)); 
     JScrollPane scroll = new JScrollPane(p); 
     frame.setContentPane(scroll); 
     frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     frame.setSize(200, 200); 
     frame.setVisible(true); 
    } 

    static public JButton getJButton(JPanel p){ 
     JButton b = new JButton("more"); 
     b.addActionListener(evt->{ 
      p.add(getJButton(p)); 
      p.revalidate(); 
      p.repaint(); 
      }); 
     return b; 
    } 
} 

Нажмите кнопку несколько раз, он будет иметь слишком много кнопок, то это активирует свиток. Это должно быть почти то, о чем вы просите.

+0

Вам просто нужно обновить() и перерисовать() панель после добавления/удаления компонента с панели. – camickr

+0

@camickr хороший звонок, я сделал изменение. – matt

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

  • Нет связанных вопросов^_^