Reputation: 2646
I have a JList that shows a list of files (with icons). I'm using DefaultListCellRenderer
to accomplish this.
However, I would only like it to show 3 columns, but its showing more. I don't want the user to have to scroll horrizontally, only vertically. How can I do that? I'm fairly new to Java.
This is my code so far:
import java.awt.Component;
import java.awt.Dimension;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.io.File;
import java.io.FileFilter;
import javax.swing.DefaultListCellRenderer;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.border.EmptyBorder;
import javax.swing.filechooser.FileSystemView;
public class StartMeUpBaby extends JFrame {
public StartMeUpBaby() {
this.setLocationRelativeTo(null);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setTitle("TESTING");
JPanel mainPanel = new JPanel();
mainPanel.setLayout(new GridBagLayout());
File f = new File(System.getProperty("user.home"));
JList<File> results = new JList<File>(f.listFiles(new FileFilter() {
public boolean accept(File file) {
String name = file.getName().toLowerCase();
return name.length() < 20;
}
}));
results.setCellRenderer(new DefaultListCellRenderer() {
public Component getListCellRendererComponent(JList<?> list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
Component component = super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
JLabel label = (JLabel)component;
File file = (File)value;
label.setText(file.getName());
label.setIcon(FileSystemView.getFileSystemView().getSystemIcon(file));
label.setBorder(new EmptyBorder(3, 3, 3, 3));
return label;
}
});
results.setLayoutOrientation(JList.HORIZONTAL_WRAP);
JScrollPane scrollPane = new JScrollPane(results, JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
scrollPane.setPreferredSize(new Dimension(408, 100));
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridx = 0;
gbc.gridy = 0;
gbc.gridwidth = 3;
gbc.gridheight = 2;
gbc.weightx = 100;
gbc.weighty = 100;
gbc.anchor = GridBagConstraints.WEST;
gbc.fill = GridBagConstraints.HORIZONTAL;
gbc.insets = new Insets(5, 5, 5, 5);
mainPanel.add(scrollPane, gbc);
this.add(mainPanel);
this.pack();
this.setVisible(true);
}
public static void main(String[] args) {
new StartMeUpBaby();
}
}
I have the preferred size set to only showing 3 columns, however if you adjust the window (make it bigger) you can see that the columns continue on.
Upvotes: 0
Views: 1158
Reputation: 44308
From the documentation of JList.setLayoutOrientation:
HORIZONTAL_WRAP
- Cells are layed out horizontally, wrapping to a new row as necessary. If thevisibleRowCount
property is less than or equal to zero, wrapping is determined by the width of the list; otherwise wrapping is done in such a way as to ensurevisibleRowCount
rows in the list.
Therefore, you can solve your problem by adding this:
results.setVisibleRowCount(0);
However, your JScrollPane size (setPreferredSize(new Dimension(488, 100))
) is arbitrary. The size needed to show three columns will depend on the file names displayed, and on visual attributes like the JList’s font. If even one fairly long file name is present, the cells will all be wider, and your size may not be sufficient.
To be completely robust, you will need to compute the preferred size based on the rendering of each file:
File f = new File(System.getProperty("user.home"));
File[] files = f.listFiles(new FileFilter() {
public boolean accept(File file) {
String name = file.getName().toLowerCase();
return name.length() < 20;
}
});
JList<File> results = new JList<File>(files) {
private Dimension maxCellSize = new Dimension();
@Override
public void addNotify() {
super.addNotify();
recomputeMaxCellSize();
}
private void recomputeMaxCellSize() {
ListCellRenderer<? super File> renderer = getCellRenderer();
if (renderer == null) {
return;
}
int fixedWidth = getFixedCellWidth();
int fixedHeight = getFixedCellHeight();
Rectangle maxCellBounds = new Rectangle();
for (int i = getModel().getSize() - 1; i >= 0; i--) {
Component c =
renderer.getListCellRendererComponent(this,
getModel().getElementAt(i), i, false, false);
Dimension cellSize = c.getPreferredSize();
maxCellBounds.add(
fixedWidth >= 0 ? fixedWidth : cellSize.width,
fixedHeight >= 0 ? fixedHeight : cellSize.height);
}
maxCellSize = maxCellBounds.getSize();
}
@Override
public Dimension getPreferredSize() {
int count = getModel().getSize();
int rows = count / 3 + (count % 3 == 0 ? 0 : 1);
return new Dimension(maxCellSize.width * 3,
maxCellSize.height * rows);
}
@Override
public Dimension getPreferredScrollableViewportSize() {
int rows = getVisibleRowCount();
if (rows <= 0) {
rows = 4;
}
return new Dimension(maxCellSize.width * 3,
maxCellSize.height * rows);
}
private final ListDataListener modelListener = new ListDataListener() {
@Override
public void intervalAdded(ListDataEvent event) {
recomputeMaxCellSize();
}
@Override
public void intervalRemoved(ListDataEvent event) {
recomputeMaxCellSize();
}
@Override
public void contentsChanged(ListDataEvent event) {
recomputeMaxCellSize();
}
};
@Override
public void setModel(ListModel<File> newModel) {
getModel().removeListDataListener(modelListener);
newModel.addListDataListener(modelListener);
super.setModel(newModel);
recomputeMaxCellSize();
}
@Override
public void setCellRenderer(ListCellRenderer<? super File> renderer) {
super.setCellRenderer(renderer);
recomputeMaxCellSize();
}
@Override
public void setFont(Font font) {
super.setFont(font);
recomputeMaxCellSize();
}
@Override
public void setFixedCellWidth(int width) {
super.setFixedCellWidth(width);
recomputeMaxCellSize();
}
@Override
public void setFixedCellHeight(int height) {
super.setFixedCellHeight(height);
recomputeMaxCellSize();
}
};
results.setVisibleRowCount(0);
Upvotes: 1
Reputation: 2646
I figured it out after a bit of research through Java Documentation.
All I had to do was add this line:
results.setVisibleRowCount(-1);
Upvotes: 0