在文件选择器中更改附件组件的位置

我在更改文件选择器中附件组件的位置时遇到问题。

我通过在文件选择器的附件组件中放置一个复选框来自定​​义保存文件对话框。 但是复选框的位置不好,真的很难看。

我可以将附件组件移动到文件窗格下面吗? 怎么做?

或者,如果您有其他解决方案来做同样的事情,也欢迎。

感谢你们。

我使用以下代码添加复选框:

JFileChooser fc = new JFileChooser(file) JPanel accessory = new JPanel(); JCheckBox isOpenBox = new JCheckBox("Open file after saving"); accessory.setLayout(new BorderLayout()); accessory.add(isOpenBox, BorderLayout.SOUTH); fc.setAccessory(accessory); 

在此屏幕截图中,复选框的位置不佳。

在此处输入图像描述

这个截图是我想要的确切效果。

在此处输入图像描述

“正确”的方式是建立一个符合您要求的新UI /外观代理。 问题是,您需要执行此操作的详细信息(以OO方式)是隐藏的,要么是private ,没有公共/受保护的访问者,要么是本地定义的……这是大多数L&F代表的主要问题…谢谢你们…

所以,你最终会复制并粘贴整个课程,这样你就可以添加这个function……你需要为你想支持的每个平台做这个…

“不太理想”的方式是在JFileChooser徘徊,并拉出你需要“改造”你的要求的那些元素。 这很麻烦,它容易出错,它会做出假设并且非常容易地破坏。

就个人而言,如果我要沿着这个特定的轨道走下去,我会创建一个实用程序类,它提供了一个简单的public static方法,它允许我传递一个JFileChooser实例,并根据当前平台(和/或当前的外观和感觉),为我做的更改……或者工厂类可以自动生成一个JFileChooser修改后满足这些要求…但这只是一个想法……

让我重复一遍,对于一个非常糟糕的设计问题,这是一个非常糟糕的想法,并且旨在certificate:1-试图修改外观和感觉的问题; 2-试图按照这种方式进行工作所面临的问题和问题……

文件选择器

 import java.awt.Component; import java.awt.Container; import java.awt.EventQueue; import java.awt.GridBagConstraints; import java.awt.GridBagLayout; import java.awt.Insets; import java.util.ArrayList; import java.util.List; import javax.swing.JCheckBox; import javax.swing.JComboBox; import javax.swing.JFileChooser; import javax.swing.JTextField; import javax.swing.UIManager; import javax.swing.UnsupportedLookAndFeelException; public class Test { public static void main(String[] args) { new Test(); } public Test() { EventQueue.invokeLater(new Runnable() { @Override public void run() { try { UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) { ex.printStackTrace(); } JFileChooser fc = new JFileChooser(); List fields = findAll(JTextField.class, fc); if (fields.size() == 1) { JTextField fieldNameField = fields.get(0); Container parent = fieldNameField.getParent(); JCheckBox cb = new JCheckBox("Open file after saving"); JComboBox fileTypes = findAll(JComboBox.class, parent).get(0); parent.setLayout(new GridBagLayout()); parent.removeAll(); GridBagConstraints gbc = new GridBagConstraints(); gbc.gridx = 0; gbc.gridy = 0; gbc.fill = GridBagConstraints.HORIZONTAL; gbc.weightx = 1; gbc.insets = new Insets(2, 2, 4, 2); parent.add(fieldNameField, gbc); // file name field... gbc.gridx++; gbc.weightx = 0; parent.add(cb, gbc); // Check box gbc.gridx = 0; gbc.gridy++; gbc.gridwidth = GridBagConstraints.REMAINDER; parent.add(fileTypes, gbc); // File types } else { System.out.println("Found to many results?!"); } fc.showOpenDialog(null); } }); } public  List findAll(Class aClass, Container parent) { List matches = new ArrayList<>(); for (Component child : parent.getComponents()) { if (aClass.isInstance(child)) { matches.add((T)child); } if (child instanceof Container) { matches.addAll(findAll(aClass, (Container)child)); } } return matches; } } 

不,我不自豪……需要用漂白剂去洗眼睛和大脑…… icky ……

更新了Mac支持

对于那些想要Mac版本的人来说……

Mac文件选择器

这进一步凸显了这种方法的“片状”,打破它不会花费太多时间……

 import java.awt.Component; import java.awt.Container; import java.awt.EventQueue; import java.util.ArrayList; import java.util.List; import javax.swing.JCheckBox; import javax.swing.JFileChooser; import javax.swing.JLabel; import javax.swing.UIManager; import javax.swing.UnsupportedLookAndFeelException; public class Test { public static void main(String[] args) { new Test(); } public Test() { EventQueue.invokeLater(new Runnable() { @Override public void run() { try { UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) { ex.printStackTrace(); } JFileChooser fc = new JFileChooser(); List labels = findAll(JLabel.class, fc); JCheckBox cb = new JCheckBox("Open file after saving"); JLabel fileFormatLabel = null; for (JLabel label : labels) { if ("File Format:".equals(label.getText())) { fileFormatLabel = label; } } System.out.println(fileFormatLabel); if (fileFormatLabel != null) { Container parent = fileFormatLabel.getParent(); parent.add(cb); } fc.showOpenDialog(null); } }); } public  List findAll(Class aClass, Container parent) { List matches = new ArrayList<>(); for (Component child : parent.getComponents()) { if (aClass.isInstance(child)) { matches.add((T) child); } if (child instanceof Container) { matches.addAll(findAll(aClass, (Container) child)); } } return matches; } } 

更新了基于Locale的搜索

这使用FileChooser.filesOfTypeLabelText UIManager.getString来查找File Format:键的文本,理论上,它应该使它成为一个(略微)更好的跨平台解决方案……至少它使它在mac上工作得更好。 ..

这也说明了必须开始支持多个OS的混乱…因为我只有两个……

 import java.awt.Component; import java.awt.Container; import java.awt.EventQueue; import java.awt.GridBagConstraints; import java.awt.GridBagLayout; import java.awt.Insets; import java.util.ArrayList; import java.util.List; import java.util.Locale; import javax.swing.JCheckBox; import javax.swing.JComboBox; import javax.swing.JFileChooser; import javax.swing.JLabel; import javax.swing.JTextField; import javax.swing.UIManager; import javax.swing.UnsupportedLookAndFeelException; public class Test1 { public static void main(String[] args) { new Test1(); } public Test1() { EventQueue.invokeLater(new Runnable() { @Override public void run() { try { UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) { ex.printStackTrace(); } JFileChooser fc = new JFileChooser(); JCheckBox cb = new JCheckBox("Open file after saving"); if (System.getProperty("os.name").startsWith("Windows 7")) { List fields = findAll(JTextField.class, fc); if (fields.size() == 1) { JTextField fieldNameField = fields.get(0); Container parent = fieldNameField.getParent(); JComboBox fileTypes = findAll(JComboBox.class, parent).get(0); parent.setLayout(new GridBagLayout()); parent.removeAll(); GridBagConstraints gbc = new GridBagConstraints(); gbc.gridx = 0; gbc.gridy = 0; gbc.fill = GridBagConstraints.HORIZONTAL; gbc.weightx = 1; gbc.insets = new Insets(2, 2, 4, 2); parent.add(fieldNameField, gbc); // file name field... gbc.gridx++; gbc.weightx = 0; parent.add(cb, gbc); // Check box gbc.gridx = 0; gbc.gridy++; gbc.gridwidth = GridBagConstraints.REMAINDER; parent.add(fileTypes, gbc); // File types } } else if (System.getProperty("os.name").startsWith("Mac OS X")) { Locale l = fc.getLocale(); JLabel fileFormatLabel = findLabelByText(fc, UIManager.getString("FileChooser.filesOfTypeLabelText", l), "Format:"); if (fileFormatLabel != null) { Container parent = fileFormatLabel.getParent(); System.out.println(""); parent.add(cb); } } fc.showOpenDialog(null); } }); } public JLabel findLabelByText(Container parent, String... texts) { JLabel find = null; List labels = findAll(JLabel.class, parent); for (JLabel label : labels) { for (String text : texts) { if (text.equals(label.getText())) { find = label; break; } } } return find; } public  List findAll(Class aClass, Container parent) { List matches = new ArrayList<>(); for (Component child : parent.getComponents()) { if (aClass.isInstance(child)) { matches.add((T) child); } if (child instanceof Container) { matches.addAll(findAll(aClass, (Container) child)); } } return matches; } } 

更新了reflection……

由于我已经为以前的“黑客”打算使用程序员地狱,我不妨投入使用reflection来查找字段的示例。

现在,您可以通过多种方式执行此操作,例如,您可以按类型列出所有字段,并检查各种属性以确定您想要的内容。 当您不知道实际字段名称时,将使用此名称。如果您有权访问源代码,则可以直接查找字段名称,如本示例中所示

 import java.awt.Component; import java.awt.Container; import java.awt.EventQueue; import java.awt.GridBagConstraints; import java.awt.GridBagLayout; import java.awt.Insets; import java.lang.reflect.Field; import java.util.ArrayList; import java.util.List; import java.util.Locale; import java.util.logging.Level; import java.util.logging.Logger; import javax.swing.JCheckBox; import javax.swing.JComboBox; import javax.swing.JFileChooser; import javax.swing.JLabel; import javax.swing.JTextField; import javax.swing.UIManager; import javax.swing.UnsupportedLookAndFeelException; import javax.swing.plaf.FileChooserUI; public class Test1 { public static void main(String[] args) { new Test1(); } public Test1() { EventQueue.invokeLater(new Runnable() { @Override public void run() { try { UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) { ex.printStackTrace(); } JFileChooser fc = new JFileChooser(); JCheckBox cb = new JCheckBox("Open file after saving"); if (System.getProperty("os.name").startsWith("Windows 7")) { try { JTextField filenameTextField = (JTextField) getField("filenameTextField", fc.getUI()); JComboBox filterComboBox = (JComboBox) getField("filterComboBox", fc.getUI()); System.out.println(filenameTextField); System.out.println(filterComboBox); Container parent = filenameTextField.getParent(); parent.setLayout(new GridBagLayout()); parent.removeAll(); GridBagConstraints gbc = new GridBagConstraints(); gbc.gridx = 0; gbc.gridy = 0; gbc.fill = GridBagConstraints.HORIZONTAL; gbc.weightx = 1; gbc.insets = new Insets(2, 2, 4, 2); parent.add(filenameTextField, gbc); // file name field... gbc.gridx++; gbc.weightx = 0; parent.add(cb, gbc); // Check box gbc.gridx = 0; gbc.gridy++; gbc.gridwidth = GridBagConstraints.REMAINDER; parent.add(filterComboBox, gbc); // File types } catch (NoSuchFieldException | SecurityException | IllegalArgumentException | IllegalAccessException ex) { ex.printStackTrace(); } } else if (System.getProperty("os.name").startsWith("Mac OS X")) { try { JComboBox filterComboBox = (JComboBox) getField("filterComboBox", fc.getUI()); Container parent = filterComboBox.getParent(); parent.add(cb); } catch (NoSuchFieldException | IllegalArgumentException | IllegalAccessException ex) { ex.printStackTrace(); } } fc.showOpenDialog(null); } }); } private Object getField(String name, Object parent) throws NoSuchFieldException, IllegalArgumentException, IllegalAccessException { Class aClass = parent.getClass(); Field field = aClass.getDeclaredField(name); field.setAccessible(true); return field.get(parent); } } 

记住:只因为你可以做某事,并不意味着你应该做!