I created a JList
inside a JScrollPane
that uses a custom ListCellRenderer
. The ListCellRenderer
contains a Jlabel
that wraps its contents with HTML so the text automatically wraps. Without using the the JScrollPane
the wrapping works, but when I use the JScrollPane
the text is not wrapped and a horizontal scrollbar appears.
Excerpt of my ListCellRenderer
:
public class WorkableCellRenderer implements ListCellRenderer<Workable> {
@Override
public final Component getListCellRendererComponent(final JList<? extends Workable> list, final Workable value,
final int index, final boolean isSelected, final boolean isFocused) {
JPanel cell = new JPanel();
cell.setLayout(new BoxLayout(cell, BoxLayout.Y_AXIS));
// ...
JPanel pnlDescription = new JPanel();
cell.add(pnlDescription);
pnlDescription.setLayout(new BorderLayout());
JLabel lblDescription =
new JLabel("<html><p style=\"margin: 0; padding: 0;\">" + value.getDescription() + "</p></html>");
lblDescription.setFont(lblDescription.getFont().deriveFont(Font.PLAIN));
pnlDescription.add(lblDescription, BorderLayout.CENTER);
// ...
return cell;
}
}
The method that adds my list to the JFrame
:
private void addLoadedModulesPanel() {
pnlLoadedModulesWrapper = new JPanel();
pnlBottom.add(pnlLoadedModulesWrapper, BorderLayout.CENTER);
pnlLoadedModulesWrapper.setLayout(new MigLayout("insets 0 5 5 5", "[grow]", "[grow]"));
pnlLoadedModulesBox = new JPanel();
pnlLoadedModulesWrapper.add(pnlLoadedModulesBox, "cell 0 0,grow");
pnlLoadedModulesBox.setLayout(new MigLayout("insets 3", "[grow]", "[grow]"));
pnlLoadedModulesBox.setBorder(BorderFactory.createTitledBorder("Geladene Module"));
lstLoadedModules = new JList<Workable>(DefaultWorkableManager.getInstance());
lstLoadedModules.setCellRenderer(new WorkableCellRenderer());
final JScrollPane listScroller = new JScrollPane(lstLoadedModules);
pnlLoadedModulesBox.add(listScroller, "cell 0 0,grow");
}
I think that the problem is the viewport of the JScrollPane
because it is bigger than the JScrollPane
itself. How can I adjust the viewports width so that it has always the same width as the JScrollPane
?
Here is a MCVE which shows my problem:
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.EventQueue;
import javax.swing.DefaultListModel;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.ListCellRenderer;
import javax.swing.border.EmptyBorder;
public class TestFrame extends JFrame {
private static final long serialVersionUID = -5281126214046039839L;
public static void main(final String[] args) {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
try {
final TestFrame frame = new TestFrame();
frame.setVisible(true);
} catch (final Exception e) {
e.printStackTrace();
}
}
});
}
public TestFrame() {
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setSize(200, 500);
getContentPane().setLayout(new BorderLayout());
final JPanel mainPanel = new JPanel();
mainPanel.setLayout(new BorderLayout());
mainPanel.setBorder(new EmptyBorder(5, 5, 5, 5));
getContentPane().add(mainPanel);
final DefaultListModel<String> lm = new DefaultListModel<>();
final JList<String> list = new JList<>(lm);
list.setCellRenderer(new MyListCellRenderer());
final JScrollPane scrollPane = new JScrollPane(list);
mainPanel.add(scrollPane);
for (int i = 1; i < 21; i++) {
lm.addElement(String.valueOf(i));
}
}
private class MyListCellRenderer implements ListCellRenderer<String> {
private final JPanel panel = new JPanel();
private final JLabel label = new JLabel();
public MyListCellRenderer() {
panel.setLayout(new BorderLayout());
panel.setBackground(new Color(16777215));
panel.add(label);
}
@Override
public Component getListCellRendererComponent(final JList<? extends String> list, final String val,
final int index, final boolean isSelected, final boolean hasFocus) {
label.setText("<html><p>Item number " + val
+ " contains some very long text, that ideally should wrap.</p></html>");
if (isSelected) {
panel.setBackground(new Color(5323));
} else {
panel.setBackground(new Color(16777215));
}
return panel;
}
}
}