Java 更改附件组件在文件选择器中的位置
我在更改文件选择器中附件组件的位置时遇到问题 我在文件选择器的附件组件中设置了一个复选框,定制了一个“保存文件”对话框。但是复选框的位置不好,它真的很难看 我可以将附件组件移动到文件窗格下方吗?怎么做 或者,如果您有其他解决方案来做同样的事情,也欢迎 谢谢你们 我使用以下代码添加复选框:Java 更改附件组件在文件选择器中的位置,java,swing,custom-component,jfilechooser,jcheckbox,Java,Swing,Custom Component,Jfilechooser,Jcheckbox,我在更改文件选择器中附件组件的位置时遇到问题 我在文件选择器的附件组件中设置了一个复选框,定制了一个“保存文件”对话框。但是复选框的位置不好,它真的很难看 我可以将附件组件移动到文件窗格下方吗?怎么做 或者,如果您有其他解决方案来做同样的事情,也欢迎 谢谢你们 我使用以下代码添加复选框: JFileChooser fc = new JFileChooser(file) JPanel accessory = new JPanel(); JCheckBox isOpenBox = new JChec
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/外观委托,以满足您的需求。问题是,您需要执行此操作的详细信息(以面向对象的方式)被隐藏,或者是private
,没有公共/受保护的访问器,或者是本地定义的访问器…这是大多数L&F代表的一个主要问题…谢谢大家
所以,你最终会复制和粘贴整个类,这样你就可以添加这一个功能…你需要为你想要支持的每个平台都这样做
“不太理想”的方法是在JFileChooser
中搜索并提取那些需要“改进”需求的元素。这是混乱的,它容易出错,它会做出假设,并且会非常非常容易地被打破
就个人而言,如果我要走这条特殊的道路,我会创建一个实用程序类,它提供一个简单的public
,static
方法,允许我传递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;
}
}
用反射更新…
由于我已经为之前的“hacks”下了地狱,我不妨加入一个使用反射查找字段的示例
现在,有很多方法可以做到这一点,例如,可以按类型列出所有字段,并检查各种属性以确定所需内容。如果您不知道实际的字段名,或者如果您可以访问源代码,可以直接查找字段名,如本例所示
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);
}
}
记住:仅仅因为你能做某事,并不意味着你应该做 您需要创建UI委托并从头开始重建UI。然后,您将需要为您想要支持的每个平台提供一个代理,以确保它不会在不同的平台上完全出错。在
基本文件选择器UI
中迁移,显然它没有对UI设置进行核心选择。仔细查看WindowsFileChooserUI
,您可能需要的所有字段/容器实际上都是private
或创建的locally@MadProgrammer谢谢,但听起来很复杂。我不知道如何构建UI委托,所以有没有更简单的方法?再次感谢:)@AnpingWang简短的回答是“不”,这不是一个非常重要的问题portable@MadProgrammer好的,谢谢。如果我们必须使用代理的东西,我怎么做?你能提供一些示例代码吗?或者一些外部链接也不错。谢谢你真的需要了解这种方法的危险性,它是一种肮脏的、肮脏的黑客行为,是由对当前界面设计的假设构成的……非常非常小心,我明白了。非常感谢你。它给了我一个解决这个问题的好主意。我会做更多的研究。非常感谢。在尝试查找JComboBox
父项时,在com.apple.laf.AquaLookAndFeel
上抛出IndexOutOfBoundsException
;脆性指数高::-)@垃圾天啊,可能不在同一条线上container@trashgod仅仅因为我已经进入(或已经进入)程序员的地狱,我用反射做了一个版本。。。
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);
}
}