java - 在 JFileChooser 中调整 JList 文件元素的大小

标签 java swing awt jlist jfilechooser

我有一个JFileChooser。我正在尝试向文件 JList 添加缩放功能。

我想更改列表中每个元素的文件名和文件图标的比例因子。

我们怎样才能实现这一目标?

最佳答案

好吧,我发现了一些丑陋的懒惰技巧来做到这一点。 它可能不正是您想要的,但它是一个很好的起点(而且相当简单):

import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import javax.swing.DefaultListCellRenderer;
import javax.swing.JButton;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JPanel;
import javax.swing.plaf.basic.BasicListUI;

public class TJFileChooserDemo {

    //Obtains the (first) JList which is found inside the component/container:
    public static JList getFirstJList(final Component component) {
        if (component instanceof JList)
            return (JList) component;
        if (component instanceof Container)
            for (int i=0; i<((Container)component).getComponentCount(); ++i) {
                final JList list = getFirstJList(((Container)component).getComponent(i));
                if (list != null)
                    return list;
            }
        return null;
        //As you can see, it's a bit lazy hack, which has to run for every JFileChooser once at start-up.
    }

    private static final double SCALE_STEP_SIZE = 0.125; //Smaller values of this makes zooming slower. Greater values makes zooming faster.
    private static double scaleFactor = 1;

    public static class TJListCellRenderer extends DefaultListCellRenderer {
        public TJListCellRenderer() {
            //Ensure every pixel is painted starting from the top-left corner of the label:
            super.setVerticalAlignment(JLabel.TOP);
            super.setHorizontalAlignment(JLabel.LEFT);
            //We need to do this, because the scaling in paintComponent() is also relative to the top-left corner.
        }

        @Override
        public void paintComponent(final Graphics g) {
            //setRenderingHints here? Probably for ANTIALIAS...
            ((Graphics2D)g).scale(scaleFactor, scaleFactor); //Let's scale everything that is painted afterwards:
            super.paintComponent(g); //Let's paint the (scaled) JLabel!
        }

        @Override
        public Dimension getPreferredSize() {
            final Dimension superPrefDim = super.getPreferredSize(); //Handles automatically insets, icon size, text font, etc.
            final double w = superPrefDim.width * scaleFactor, //And we just scale the preferred size.
                         h = superPrefDim.height * scaleFactor; //And we just scale the preferred size.
            return new Dimension((int)w + 5, (int)h + 5); //Add 5 extra pixels to spare.
        }

        @Override
        public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
//            System.out.println(value.getClass()); //Something ugly...
            return super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
        }
    }

    public static class TJListUI extends BasicListUI {
        @Override
        public void updateLayoutState() {
            super.updateLayoutState(); //Just make the following method public.
            /*Note: this is not really needed here:
            The method could remain protected, but in the case you want this
            code to be a bit more reusable, then you shall make it public.*/
        }
    }

    public static void main(final String[] args) {
        final JFileChooser jfc = new JFileChooser();
        jfc.setDialogType(JFileChooser.OPEN_DIALOG);

        final TJListUI ui = new TJListUI();

        final JList list = getFirstJList(jfc);
        list.setUI(ui);
        list.setCellRenderer(new TJListCellRenderer());

        final JButton buttonZoomIn = new JButton("Zoom in"),
                      buttonZoomOut = new JButton("Zoom out"),
                      buttonResetZoom = new JButton("Reset zoom");

        buttonZoomIn.addActionListener(e -> {
            scaleFactor = scaleFactor + SCALE_STEP_SIZE;
            ui.updateLayoutState(); //Read the preferred sizes from the cell renderer.
            list.revalidate(); //Update the JScrollPane.
            list.repaint(); //Repaint the list.
        });

        buttonZoomOut.addActionListener(e -> {
            scaleFactor = Math.max(scaleFactor - SCALE_STEP_SIZE, SCALE_STEP_SIZE); //Do not allow underflow.
            ui.updateLayoutState(); //Read the preferred sizes from the cell renderer.
            list.revalidate(); //Update the JScrollPane.
            list.repaint(); //Repaint the list.
        });

        buttonResetZoom.addActionListener(e -> {
            scaleFactor = 1;
            ui.updateLayoutState(); //Read the preferred sizes from the cell renderer.
            list.revalidate(); //Update the JScrollPane.
            list.repaint(); //Repaint the list.
        });

        final JPanel buttons = new JPanel(); //FlowLayout.
        buttons.add(buttonZoomIn);
        buttons.add(buttonZoomOut);
        buttons.add(buttonResetZoom);

        final JPanel panel = new JPanel(new BorderLayout());
        panel.add(buttons, BorderLayout.PAGE_START);
        panel.add(jfc, BorderLayout.CENTER);

        final JFrame frame = new JFrame("JFileChooser's JList cell sizes demo");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.getContentPane().add(panel);
        frame.pack();
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    }
}

或者你可以查看我的回答 here关于 JList 的单独可调整大小的单元格。

您还可以添加 JFileChooser 的放大/缩小按钮,如 accessory 。阅读 this简单的例子说明如何做到这一点。

测试此代码,我正在等待评论...

关于java - 在 JFileChooser 中调整 JList 文件元素的大小,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51161392/

相关文章:

java - 调用 repaint() 而不丢失先前的图形

java - 为什么我不能将 ArrayList 直接添加到 Jlist 中?

java - KeyListener 和 boolean 值不起作用

java - java中的垂直选框JLabel?

java - 对于每个循环不返回值?

Java Excel Api字符编码问题

java - 将 JPanel 添加到 Javafx

java - 当有其他窗口时,第一个 NewtCanvasAWT 中的第一个 GLWindow 不会得到 .repaint()

java - 从 linux Deepin 15 中的 java 应用程序打印在 jaspersoft studio 中制作的报告时出错

java - 从 Pane 中删除元素时,阻止 GridBagLayout 调整列/行的大小?