在文件选择器中更改附件组件的位置 [英] Change the location of the accessory component in a filechooser

查看:129
本文介绍了在文件选择器中更改附件组件的位置的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I have a problem in changing the location of the accessory component in a filechooser.

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

I customized a save file dialog by putting a check box in the accessory component of the file chooser. But the position of the check box is not good, it is really ugly.

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

Can I move the accessory component to be underneath the file pane? How to do it?

或者,如果你有其他解决办法做同样的事情,也欢迎。

Or if you have other solution to do the same thing, also welcome.

谢谢你们。

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

I using following code to add the check box:

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

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

In this screenshot, the position of the check box is not good.

此屏幕截图正是我想要的效果。

This screenshot is the exactly effect I want.

推荐答案

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

The "right" way would be to build a new UI/Look and Feel delegate which meet your requirements. The problem is, the details you need to do this (in an OO way) are hidden, either private with no public/protected accessor or defined locally...this is a major problem with most of the L&F delegates...thanks guys...

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

So, you'd end up copying and pasting the entire class, just so you can add this one feature...and you'd need to do this for EVERY platform you wanted to support...

不太理想的方式,是在 JFileChooser 中徘徊,并提取你需要改进你的要求的那些元素。这很麻烦,它很容易出错,它会做出假设并且很容易打破。

The "less than optimal" way, is to ferret around within the JFileChooser and pull out those elements you need to "retrofit" your requirements. This is messy, it's error prone, it makes assumptions and will break very, very easily.

就个人而言,如果我要走这条特定的赛道,我会创造一个实用程序类,它提供了一个简单的 public static 方法,它允许我传递一个 JFileChooser 并根据当前平台(和/或当前的外观)对其进行更改...或者可以自动生成<$ c $的工厂类c> JFileChooser 经过修改以满足这些要求......但这只是一个想法...

Personally, if I was to go down this particular track, I would create a utility class which provides a simple public, static method which would allow me to pass an instance of JFileChooser and have it, based on the current platform (and/or the current look and feel), make the changes for me...or a factory class that could auto generate a JFileChooser modified to meet those requirements...but this is just an idea...

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

Let me re-iterate this, this is a very bad idea to a very poor design problem and is meant to demonstrate: 1- The problems with trying to modify a look and feel; 2- The problems and issues you will face in attempting to make this work the way want it to...

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 ...

And no, I'm not proud...need to go wash my eyes and brain out with bleach...icky...

更新了Mac支持

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

And for those who would like a Mac version...

这只是进一步突出了这种方法的片状,它不会需要花很多时间来打破它...

This just further highlights the "flakiness" of this approach, it won't take much to break it...

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

}

以<$更新c $ c>基于区域设置的搜索

Updated with Locale based searching

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

This uses the FileChooser.filesOfTypeLabelText UIManager.getString to look up the text of the File Format: key, which in theory, should make it a (slightly) better cross platform solution...at least it makes it work better on the mac...

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

This also demonstrates the mess of having to start to support multiple OS...Since I only have two...

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

}

用反射更新。 ..

由于我已经为以前的黑客打算编程地狱,我不妨投入一个使用反射的例子找到这些字段。

Since I'm already going to programmer hell for the previous "hacks", I might as well as throw in an example of using reflection to find the fields.

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

Now, there are a number of ways you might do this, you could list all the fields by type, for example and inspect various properties to determine what you want. This would be used when you don't know the actual field name OR, if you have access to the source code, you can look up the field names directly, as is done in this example

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

}

记住:只因为你能做点什么,并不代表你应该做的事情!

Remember: Just because you can do something, doesn't mean you should!

这篇关于在文件选择器中更改附件组件的位置的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆