stevecross
stevecross

Reputation: 5684

Limit the width of a JScrollpane containing a JList

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;
        }
    }

}

Upvotes: 0

Views: 964

Answers (2)

camickr
camickr

Reputation: 324207

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?

You need to implement the Scrollable interface on your panel to limit the width of the panel to the width of the scroll pane.

Or you can use the Scrollable Panel which provides a couple of methods that allow you to control this behaviour.

Upvotes: 1

mKorbel
mKorbel

Reputation: 109823

everything depends ..., then JList in JScrollPane can returns proper getPreferredSize (or directly by using JList.setPrototypeCellValue) for used LayoutManager

  1. whats is value for getPreferredSize returns ListCellRenderer, is this PreferredSize the same for all Items or not

  2. how is set for JList.setLayoutOrientation()

  3. is there used limits for visible row or not JList.setVisibleRowCount()

Upvotes: 2

Related Questions