2011-02-10 142 views
14

Swing組件我有一個JFrame一些組件,我想 指到另一個JFrame,我想 的名字,讓他們不 做每個公共get/set方法。按名稱獲取

有沒有一種方法可以從Swing獲取組件引用的名稱,就像do c#?

例如form.Controls["text"]

感謝

+1

Window.getWindows()然後掃描你需要的東西 – bestsss 2011-02-10 15:05:56

+1

爲什麼你想在世界上這樣做?通過這樣做,您將失去兩個重要的靜態編譯器檢查: - 首先,該字段存在。 - 其次,它是正確的類型。另外,動態查詢比引用該字段要慢。 – fortran 2011-02-10 15:11:23

回答

27

我知道這是一個古老的問題,但我發現自己現在就問它。我想要一個簡單的方法來按名稱獲取組件,所以我不必每次都寫一些令人費解的代碼來訪問不同的組件。例如,讓JButton訪問文本字段中的文本或List中的選擇。

最簡單的解決方案是使所有組件變量都是類變量,以便您可以隨時隨地訪問它們。然而,並不是每個人都想這樣做,而且有些人(比如我自己)正在使用GUI編輯器,它們不會將這些組件生成爲類變量。據我所知(參考fortran的進展情況),我的解決方案很簡單,我想,並沒有真正違反任何編程標準。它允許以簡單直接的方式按名稱訪問組件。

  1. 創建一個Map類變量。您至少需要在 處導入HashMap。我簡單地命名了我的componentMap。

    private HashMap componentMap; 
    
  2. 正常情況下將所有組件添加到框架中。

    initialize() { 
        //add your components and be sure 
        //to name them. 
        ... 
        //after adding all the components, 
        //call this method we're about to create. 
        createComponentMap(); 
    } 
    
  3. 在你的類中定義以下兩種方法。你需要進口元件,如果您尚未:

    private void createComponentMap() { 
         componentMap = new HashMap<String,Component>(); 
         Component[] components = yourForm.getContentPane().getComponents(); 
         for (int i=0; i < components.length; i++) { 
           componentMap.put(components[i].getName(), components[i]); 
         } 
    } 
    
    public Component getComponentByName(String name) { 
         if (componentMap.containsKey(name)) { 
           return (Component) componentMap.get(name); 
         } 
         else return null; 
    } 
    
  4. 現在你已經得到了所有當前存在的組件映射在幀/內容窗格/板/等,以各自的名稱一個HashMap 。

  5. 現在訪問這些組件,就像調用getComponentByName(String name)一樣簡單。如果存在具有該名稱的組件,它將返回該組件。如果不是,則返回null。您有責任將組件轉換爲適當的類型。我建議使用instanceof來確保。

如果您計劃在運行時的任何時候添加,刪除或重命名組件,我會考慮根據您的更改添加修改HashMap的方法。

1

可以聲明一個變量作爲一個公衆一個再得到你想要的文字或任何操作,然後就可以在其他幀訪問它(如果在同一個包),因爲它是公衆。

2

您可以在第二個JFrame中持有對第一個JFrame的引用,並通過JFrame.getComponents()循環檢查每個元素的名稱。

6

每個Component可以有一個名稱,通過getName()setName()訪問,但你必須編寫自己的查找功能。

4

getComponentByName(框架名)

如果你正在使用NetBeans或默認創建私有變量(領域)的另一個IDE來保存你所有的AWT/Swing組件,然後將下面的代碼可能會工作爲你。使用方法如下:

// get a button (or other component) by name 
JButton button = Awt1.getComponentByName(someOtherFrame, "jButton1"); 

// do something useful with it (like toggle it's enabled state) 
button.setEnabled(!button.isEnabled()); 

這裏有上作出上述可能的代碼...

import java.awt.Component; 
import java.awt.Window; 
import java.lang.reflect.Field; 

/** 
* additional utilities for working with AWT/Swing. 
* this is a single method for demo purposes. 
* recommended to be combined into a single class 
* module with other similar methods, 
* e.g. MySwingUtilities 
* 
* @author http://javajon.blogspot.com/2013/07/java-awtswing-getcomponentbynamewindow.html 
*/ 
public class Awt1 { 

    /** 
    * attempts to retrieve a component from a JFrame or JDialog using the name 
    * of the private variable that NetBeans (or other IDE) created to refer to 
    * it in code. 
    * @param <T> Generics allow easier casting from the calling side. 
    * @param window JFrame or JDialog containing component 
    * @param name name of the private field variable, case sensitive 
    * @return null if no match, otherwise a component. 
    */ 
    @SuppressWarnings("unchecked") 
    static public <T extends Component> T getComponentByName(Window window, String name) { 

     // loop through all of the class fields on that form 
     for (Field field : window.getClass().getDeclaredFields()) { 

      try { 
       // let us look at private fields, please 
       field.setAccessible(true); 

       // compare the variable name to the name passed in 
       if (name.equals(field.getName())) { 

        // get a potential match (assuming correct &lt;T&gt;ype) 
        final Object potentialMatch = field.get(window); 

        // cast and return the component 
        return (T) potentialMatch; 
       } 

      } catch (SecurityException | IllegalArgumentException 
        | IllegalAccessException ex) { 

       // ignore exceptions 
      } 

     } 

     // no match found 
     return null; 
    } 

} 

它使用反射通過類領域看,看它是否可以找到被稱爲組件由一個相同名稱的變量。

注意:上面的代碼使用泛型將結果轉換爲您期望的任何類型,因此在某些情況下,您可能必須明確指定類型轉換。例如,如果myOverloadedMethod同時接受JButtonJTextField,你可能需要明確定義你要撥打的過載...

myOverloadedMethod((JButton) Awt1.getComponentByName(someOtherFrame, "jButton1")); 

如果你不知道,你可以得到一個Componentinstanceof檢查...

// get a component and make sure it's a JButton before using it 
Component component = Awt1.getComponentByName(someOtherFrame, "jButton1"); 
if (component instanceof JButton) { 
    JButton button = (JButton) component; 
    // do more stuff here with button 
} 

希望這有助於!

1

我需要訪問幾個JPanel之內的元素,這些元素在單個JFrame之內。

@Jesse Strickland發佈了一個很好的答案,但是提供的代碼無法訪問任何嵌套元素(就像在我的情況下,在JPanel內部)。

經過額外的Google搜索後,我發現@aioobe here提供了這種遞歸方法。

通過組合和修改稍微斯特里克蘭@Jesse和@​​aioobe的代碼,我可以訪問所有的嵌套元素,無論他們有多深是一個工作代碼:代碼

private void createComponentMap() { 
    componentMap = new HashMap<String,Component>(); 
    List<Component> components = getAllComponents(this); 
    for (Component comp : components) { 
     componentMap.put(comp.getName(), comp); 
    } 
} 

private List<Component> getAllComponents(final Container c) { 
    Component[] comps = c.getComponents(); 
    List<Component> compList = new ArrayList<Component>(); 
    for (Component comp : comps) { 
     compList.add(comp); 
     if (comp instanceof Container) 
      compList.addAll(getAllComponents((Container) comp)); 
    } 
    return compList; 
} 

public Component getComponentByName(String name) { 
    if (componentMap.containsKey(name)) { 
     return (Component) componentMap.get(name); 
    } 
    else return null; 
} 

用法與@Jesse Strickland代碼完全一樣。

0

如果您的組件是在同一個類中聲明的,那麼您只需以的類名稱即可訪問這些組件。

public class TheDigitalClock { 

    private static ClockLabel timeLable = new ClockLabel("timeH"); 
    private static ClockLabel timeLable2 = new ClockLabel("timeM"); 
    private static ClockLabel timeLable3 = new ClockLabel("timeAP"); 


    ... 
    ... 
    ... 


      public void actionPerformed(ActionEvent e) 
      { 
       ... 
       ... 
       ... 
        //set all components transparent 
        TheDigitalClock.timeLable.setBorder(null); 
        TheDigitalClock.timeLable.setOpaque(false); 
        TheDigitalClock.timeLable.repaint(); 

        ... 
        ... 
        ... 

       } 
    ... 
    ... 
    ... 
} 

而且,你可以能夠訪問類組件如在同一個名字太從其他類的類名的屬性。我可以訪問受保護的屬性(類成員變量),也許你也可以訪問公共組件。嘗試一下!