编程语言
首页 > 编程语言> > java – 在文件选择器中更改附件组件的位置

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

作者:互联网

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

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

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

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

感谢大伙们.

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

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方式)是隐藏的,要么是私有的,没有公共/受保护的访问者,要么是本地定义的……这是大多数L& F代表的主要问题……多谢你们…

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

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

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

让我重复一遍,对于一个非常糟糕的设计问题,这是一个非常糟糕的想法,并且旨在证明: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<JTextField> 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 <T extends Component> List<T> findAll(Class<? extends T> aClass, Container parent) {
        List<T> 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版本的人来说……

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

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<JLabel> 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 <T extends Component> List<T> findAll(Class<? extends T> aClass, Container parent) {
        List<T> 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;
    }

}

更新了基于区域设置的搜索

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

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

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<JTextField> 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<JLabel> labels = findAll(JLabel.class, parent);
        for (JLabel label : labels) {
            for (String text : texts) {
                if (text.equals(label.getText())) {
                    find = label;
                    break;
                }
            }
        }
        return find;
    }

    public <T extends Component> List<T> findAll(Class<? extends T> aClass, Container parent) {
        List<T> 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;
    }

}

更新了反射……

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

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

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

}

记住:只因为你可以做某事,并不代表你应该做的事!

标签:jfilechooser,jcheckbox,custom-component,java,swing
来源: https://codeday.me/bug/20191001/1839340.html