[英]Resize JList file elements in JFileChooser
I have a JFileChooser
. 我有一个
JFileChooser
。 I am trying to add a zoom feature to the files JList
. 我正在尝试向文件
JList
添加缩放功能。
I would like to change the scale factor of the file name and of the file icon, for each element of the list. 我想为列表的每个元素更改文件名和文件图标的比例因子。
How could we achieve this ? 我们如何实现这一目标?
Should I make a custom renderer
like here [JList custom renderer example] ( http://www.codejava.net/java-se/swing/jlist-custom-renderer-example ) 我是否应该像这里一样制作
custom renderer
[JList自定义渲染器示例]( http://www.codejava.net/java-se/swing/jlist-custom-renderer-example )
or change the list Model
? 或更改列表
Model
?
Well, I found out some ugly lazy hacks to do it. 好吧,我发现了一些丑陋的懒家伙。 It might not be just what you want, but it's a good starting point (and fairly simple):
它可能不仅是您想要的,而且是一个很好的起点(并且相当简单):
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);
}
}
Alternatively you can check my answer here about individually resizable cells of a JList
. 或者,您可以在此处查看有关
JList
单独调整大小的单元格的答案。
You can also probably add the JFileChooser
's buttons for zooming in/out as an accessory . 您也可以添加
JFileChooser
的用于放大/缩小的按钮作为附件 。 Read this simple example for how to do it. 阅读此简单示例以了解操作方法。
Test this code, and I am waiting for comments... 测试此代码,我正在等待评论...
In the end, I realized scaling the text wasn't needed. 最后,我意识到不需要缩放文本。
To obtain the image files thumbnail, I used the code in making JFileChooser show image thumbnails - check BoffinbraiN answer. 为了获得图像文件缩略图,我使用了使JFileChooser显示图像缩略图的代码-检查BoffinbraiN答案。
Then for scaling : 然后进行缩放:
1) add an ActionListener
to the buttons of ThumbnailFileChooser
. 1)在
ThumbnailFileChooser
的按钮上添加一个ActionListener
。
public class ZoomListener implements ActionListener {
private boolean zoomIn = false;
private IconScaleManager iconScaleManager = null;
public ZoomListener(boolean zoom, IconScaleManager renderer) {
zoomIn = zoom;
iconScaleManager = renderer;
}
@Override
public void actionPerformed(ActionEvent e) {
iconScaleManager.scaleButton(zoomIn);
}
}
2) ActionListener::actionPerformed()
calls a scale method
of a ScaleManager
. 2)
ActionListener::actionPerformed()
调用ScaleManager
的scale method
。
@Override
public void actionPerformed(ActionEvent e) {
iconScaleManager.scaleButton(zoomIn);
}
3) The ScaleManager
method changes and update the cells of the ThumbnailFileChooser's Jlist
(the list is an attribute of the ScaleManager
) 3)
ScaleManager
方法更改并更新ThumbnailFileChooser's Jlist
的单元格(该列表是ScaleManager
的属性)
public class IconScaleManager {
static final int[] iconScales = new int[]{ 16, 32, 64, 128, 256, 512, 1024, 2048 };
private int scaleIndex = 4;
private JList fileList = null;
public IconScaleManager(JList list) {
fileList = list;
setFixedCellDimension();
}
public void scaleButton(boolean zoomIn) {
if (zoomIn && scaleIndex < iconScales.length - 1) {
scaleIndex++;
setFixedCellDimension();
} else if (!zoomIn && 0 < scaleIndex) {
scaleIndex--;
setFixedCellDimension();
}
}
private void setFixedCellDimension() {
fileList.setFixedCellWidth(iconScales[scaleIndex]);
fileList.setFixedCellHeight(iconScales[scaleIndex]);
}
}
Thank you @thanopi57 for your help. 谢谢@ thanopi57的帮助。 I didn't really use what you provided, but I appreciate your support.
我并没有真正使用您提供的内容,但感谢您的支持。
Also, I will have to make sure that it works, because there might not be a JList for all JFileChooser
另外,我必须确保它能正常工作,因为可能没有针对所有
JFileChooser
的JList
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.