2015-11-24 41 views
2

我正在嘗試在swing中創建GUI。 GUI將保持固定高度的可變數量的JPanels彼此堆疊。當堆棧中的JPanel s的總高度大於封閉框架的高度時,用戶應該能夠通過面板向上和向下滾動。在Java Swing中設置像素高度的項目的可滾動列表

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

我使用的JScrollPane S和JPanel s的GridLayoutGridBagLayout以及呼叫組合setPreferedSizesetMinimumSize沒有成功嘗試。我覺得設置這種gui應該相當簡單,但似乎無法找出解決方案。

+0

請參閱編輯回答 –

+0

'我嘗試了使用JScrollPanes和JPanels與GridLayout和GridBagLayout的組合,以及調用setPreferedSize和setMinimumSize都沒有成功。 - 不要對'setPreferredSize() 。這將防止滾動工作!只需將子面板添加到父面板,然後使用父面板創建JScrollPane,然後將該scrollPane添加到該面板。 – camickr

+0

查看最新的編輯,現在也顯示JList解決方案。 –

回答

4

如果使用JPanels,那麼由視口占據的JPanel應該覆蓋JPanel類並應實現Scrollable接口,爲覆蓋的方法返回適當的值,特別是getPreferredScrollableViewportSize()方法。儘管我的錢,我寧願使用JList,並使用適當的渲染器,而不是JPanels,然後通過其setVisibleRowCount(...)方法設置我的JLists visibleRowCount。

例如:

實例編輯到現在顯示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

相關問題