「正確」的方法是建立一個新的UI /外觀委託符合您的要求。問題是,需要做這些事情的細節(以OO方式)是隱藏的,或者沒有公共/受保護訪問者的private
或本地定義的......這是大多數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;
}
}
不,我不感到自豪......需要去洗我的眼睛和大腦出用漂白劑... ...噁心
與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;
}
}
與Locale
更新搜索
這使用FileChooser.filesOfTypeLabelText
UIManager.getString
來查找File Format:
鍵的文本,理論上它應該使其成爲(輕微ly)更好的跨平臺解決方案...至少它使得它在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);
}
}
記住:只因爲你可以做點什麼,並不代表你應該做的!
您將需要創建您的UI委託並從頭開始重建UI。然後,您需要爲每個想要支持的平臺提供一個委託,以確保它不會在不同的平臺上完全混淆。 – MadProgrammer 2014-08-27 23:27:23
圍繞'BasicFileChooserUI'進行挖掘,顯然它沒有對UI設置做出核心選擇。挖掘'WindowsFileChooserUI',你可能需要的所有字段/容器實際上是'private'或在本地創建 – MadProgrammer 2014-08-27 23:52:28
@MadProgrammer謝謝,但這聽起來很複雜。我不知道如何構建UI委託,那麼有沒有更簡單的方法來做到這一點?再次感謝:) – 2014-08-27 23:53:30