2014-08-27 80 views
2

我在更改文件選擇器中附件組件的位置時遇到問題。更改文件選擇器中附件組件的位置

我通過在文件選擇器的附件組件中添加複選框來自定​​義保存文件對話框。但複選框的位置並不好,這真的很難看。

我可以將附件組件移動到文件窗格下方嗎?怎麼做?

或者如果您有其他解決方案來做同樣的事情,也歡迎。

謝謝你們。

我用下面的代碼添加複選框:

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

在這張截圖,該複選框的位置並不好。

enter image description here

這張截圖是完全相同的效果我想要的。

enter image description here

+0

您將需要創建您的UI委託並從頭開始重建UI。然後,您需要爲每個想要支持的平臺提供一個委託,以確保它不會在不同的平臺上完全混淆。 – MadProgrammer 2014-08-27 23:27:23

+0

圍繞'BasicFileChooserUI'進行挖掘,顯然它沒有對UI設置做出核心選擇。挖掘'WindowsFileChooserUI',你可能需要的所有字段/容器實際上是'private'或在本地創建 – MadProgrammer 2014-08-27 23:52:28

+0

@MadProgrammer謝謝,但這聽起來很複雜。我不知道如何構建UI委託,那麼有沒有更簡單的方法來做到這一點?再次感謝:) – 2014-08-27 23:53:30

回答

10

「正確」的方法是建立一個新的UI /外觀委託符合您的要求。問題是,需要做這些事情的細節(以OO方式)是隱藏的,或者沒有公共/受保護訪問者的private或本地定義的......這是大多數F代表的主要問題......謝謝你們......

所以,你最終會複製和粘貼整個班級,只要你可以添加這個功能......你需要爲你想支持的每個平臺都做這個。 ..「

」不到最佳「的方式是在JFileChooser內徘徊,並提取需要」改造「您的要求的那些元素。這很混亂,容易出錯,它會做出假設,並且非常容易中斷。就個人而言,如果我要走這條軌道,我會創建一個實用程序類,它提供了一個簡單的public,static方法,該方法允許我通過一個JFileChooser的實例並基於當前平臺和/或當前的外觀和感覺),對我進行更改......或者可以自動生成JFileChooser以滿足這些要求的工廠類別...但這只是一個想法...

讓我重複了這一點,對於一個非常糟糕的設計問題來說,這是一個非常糟糕的主意,它的目的在於證明:1-嘗試修改外觀和感覺的問題; 2-困難和問題,你將面臨在試圖使這項工作的方式,要...

File Chooser

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

Mac File Chooser

這只是進一步凸顯了這種方法的 「片狀」,它不會花費太多,打破它...基於

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

} 

記住:只因爲你可以做點什麼,並不代表你應該做的!

+0

太棒了!謝謝,讓我詳細閱讀它。 :) – 2014-08-28 00:27:46

+2

你真的需要了解這種方法的危險,它是一個骯髒,骯髒的黑客,它是由接口的當前設計假設組成...非常,非常小心 – MadProgrammer 2014-08-28 00:28:41

+0

雅,我明白了。非常感謝你。它給了我一個好主意如何解決這個問題。我會做更多的研究。非常感謝你。 – 2014-08-28 00:45:25