【问题标题】:How do I wrap contents in a JList?如何将内容包装在 JList 中?
【发布时间】:2017-07-22 19:30:03
【问题描述】:

我有一个显示文件列表(带有图标)的 JList。我正在使用DefaultListCellRenderer 来完成此操作。

但是,我只希望它显示 3 列,但它会显示更多。我不希望用户必须水平滚动,只能垂直滚动。我怎样才能做到这一点?我对 Java 还很陌生。

这是我目前的代码:

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();

    }

}

我将首选大小设置为仅显示 3 列,但是如果您调整窗口(使其更大),您可以看到列继续显示。

【问题讨论】:

    标签: java file jlist horizontal-scrolling


    【解决方案1】:

    来自documentation of JList.setLayoutOrientation:

    HORIZONTAL_WRAP - 单元格水平排列,必要时换行。如果visibleRowCount属性小于等于0,则换行由列表的宽度决定;否则以确保列表中的visibleRowCount 行的方式完成包装。

    因此,您可以通过添加以下内容来解决您的问题:

    results.setVisibleRowCount(0);
    

    但是,您的 JScrollPane 大小 (setPreferredSize(new Dimension(488, 100))) 是任意的。显示三列所需的大小取决于显示的文件名,以及 JList 字体等视觉属性。如果存在一个相当长的文件名,则单元格都会变宽,并且您的大小可能不够。

    为了完全健壮,您需要根据每个文件的渲染计算首选大小:

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

    【讨论】:

      【解决方案2】:

      我在通过 Java 文档进行了一些研究后发现了这一点。

      我所要做的就是添加这一行:

      results.setVisibleRowCount(-1);
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-02-14
        • 1970-01-01
        相关资源
        最近更新 更多