2011-02-10 40 views
14

tôi có trong một JFrame một số thành phần mà tôi muốn để tham khảo vào JFrame khác và tôi muốn để có được chúng theo tên và không làm phương pháp get/set nào cho mỗi.Nhận một thành phần Swing theo tên

Có cách nào từ Swing để nhận tham chiếu thành phần theo tên của nó như làm C#?

ví dụ: form.Controls["text"]

Cảm ơn

+1

Window.getWindows() và sau đó quét những gì bạn cần – bestsss

+1

Tại sao bạn muốn làm điều đó?Bằng cách đó, bạn mất hai kiểm tra trình biên dịch tĩnh quan trọng: - Đầu tiên, trường tồn tại. - Thứ hai, đó là loại đúng. Ngoài ra, tìm kiếm động sẽ chậm hơn so với tham chiếu đến trường. – fortran

+0

Ví dụ: do API đáng sợ, nơi bạn không có quyền truy cập trực tiếp vào một số thành phần mà bạn muốn sửa đổi. –

Trả lời

27

Tôi biết đây là một câu hỏi cũ, nhưng tôi thấy bản thân mình yêu cầu nó ngay bây giờ. Tôi muốn một cách dễ dàng để có được các thành phần theo tên vì vậy tôi không phải viết một số mã phức tạp mỗi lần để truy cập các thành phần khác nhau. Ví dụ, có một JButton truy cập văn bản trong một trường văn bản hoặc một lựa chọn trong một Danh sách.

Giải pháp dễ nhất là làm cho tất cả các biến thành phần là biến lớp để bạn có thể truy cập chúng ở bất kỳ đâu. Tuy nhiên, không phải ai cũng muốn làm điều đó, và một số (như bản thân tôi) đang sử dụng Trình soạn thảo GUI không tạo ra các thành phần như các biến lớp.

Giải pháp của tôi rất đơn giản, tôi muốn suy nghĩ và không thực sự vi phạm bất kỳ tiêu chuẩn lập trình nào, theo như tôi biết (tham khảo những gì mà fortran nhận được). Nó cho phép một cách dễ dàng và đơn giản để truy cập các thành phần theo tên.

  1. Tạo biến lớp Bản đồ. Bạn sẽ cần phải nhập HashMap tại số ít nhất. Tôi đặt tên cho tôi là componentMap để đơn giản.

    private HashMap componentMap; 
    
  2. Thêm tất cả các thành phần của bạn vào khung như bình thường.

    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. Xác định hai phương pháp sau trong lớp học của bạn. Bạn sẽ cần phải nhập khẩu phần nếu bạn chưa sẵn sàng:

    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. Bây giờ bạn đã có một HashMap mà các bản đồ tất cả các thành phần hiện có trong khung hình của bạn/khung content/bảng/etc để tên của mình .

  5. Để truy cập vào các thành phần này, nó đơn giản như gọi hàm getComponentByName (Tên chuỗi). Nếu một thành phần có tên đó tồn tại, nó sẽ trả về thành phần đó. Nếu không, nó trả về null. Trách nhiệm của bạn là đưa thành phần vào đúng loại. Tôi đề nghị sử dụng instanceof để chắc chắn.

Nếu bạn có kế hoạch thêm, xóa hoặc đổi tên thành phần tại bất kỳ thời điểm nào trong thời gian chạy, tôi sẽ xem xét thêm các phương pháp sửa đổi HashMap theo thay đổi của bạn.

+0

Vâng tôi nghĩ đó là một giải pháp tốt. Cảm ơn code :) – xdevel2000

+1

Tôi gặp vấn đề với chuỗi JPanels trên mẫu của tôi. Vì vậy, một phiên bản hơi modivied cũng đi qua chứa Containers: \t thành phần riêng getComponentByName (String name) { \t \t return getComponentByName (getMainFrame(). GetRootPane(), name); \t} \t \t tin Component getComponentByName (root container, String name) { \t \t for (Component c: root.getComponents()) { \t \t \t if (name.equals (c.getName())) { \t \t \t \t trở về c; \t \t \t} \t \t \t if (c instanceof container) { \t \t \t \t kết quả Component = getComponentByName ((Container) c, tên); \t \t \t \t if (result = null) { \t \t \t \t \t kết quả trở lại; \t \t \t \t} \t \t \t} \t \t} \t \t trở lại null; \t} –

+0

Đơn giản và dễ dàng – kazy

1

Bạn có thể khai báo một biến như một công sau đó nhận được văn bản hoặc bất cứ hoạt động mà bạn muốn và sau đó bạn có thể truy cập vào nó trong khung khác (nếu trong cùng một gói) vì nó là công cộng.

2

bạn có thể giữ tham chiếu đến JFrame đầu tiên trong JFrame thứ hai và chỉ lặp qua JFrame.getComponents(), kiểm tra tên của từng phần tử.

6

Mỗi Component có thể có tên, được truy cập qua getName()setName(), nhưng bạn sẽ phải viết chức năng tra cứu của riêng mình.

4

getComponentByName (khung hình, tên)

NẾU bạn đang sử dụng NetBeans IDE này hay cách khác mà theo mặc định tạo ra các biến riêng (trường) để giữ tất cả các thành phần AWT/Swing của bạn, sau đó mã sau đây có thể làm việc cho bạn. Sử dụng như sau:

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

Dưới đây là đoạn code để làm cho trên có thể ...

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

} 

Nó sử dụng phản ánh để xem xét thông qua các lĩnh vực lớp học để xem nó có thể tìm thấy một thành phần được gọi bởi một biến cùng tên.

LƯU Ý: Mã ở trên sử dụng Generics để truyền kết quả cho bất kỳ loại nào bạn mong đợi, vì vậy trong một số trường hợp, bạn có thể phải rõ ràng về việc nhập kiểu. Ví dụ, nếu myOverloadedMethod chấp nhận cả JButtonJTextField, bạn có thể cần phải xác định một cách rõ ràng tình trạng quá tải bạn muốn gọi ...

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

Và nếu bạn không chắc chắn, bạn có thể nhận được một Component và kiểm tra xem nó với instanceof ...

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

Hy vọng điều này sẽ hữu ích!

1

Tôi cần truy cập các thành phần bên trong một số JPanel s nằm trong một đơn JFrame.

@Jesse Strickland đã đăng câu trả lời tuyệt vời, nhưng mã được cung cấp không thể truy cập bất kỳ phần tử lồng nhau nào (như trong trường hợp của tôi, bên trong JPanel).

Sau khi Google bổ sung, tôi đã tìm thấy phương pháp đệ quy này được cung cấp bởi @aioobe here.

Bằng cách kết hợp và hơi sửa đổi mã của @Jesse Strickland và @aioobe Tôi có một mã số làm việc mà có thể truy cập vào tất cả các yếu tố lồng nhau, bất kể như thế nào sâu đó là:

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

Sử dụng mã là chính xác giống như trong mã @Jesse Strickland.

0

Nếu các thành phần của bạn được khai báo bên trong cùng một lớp bạn đang thao tác chúng, bạn chỉ cần truy cập các thành phần này làm thuộc tính của tên lớp.

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

        ... 
        ... 
        ... 

       } 
    ... 
    ... 
    ... 
} 

Và, bạn có thể có thể truy cập các thành phần lớp là thuộc tính của tên lớp từ các lớp khác trong cùng một không gian tên quá. Tôi có thể truy cập các thuộc tính được bảo vệ (các biến thành viên lớp), có thể bạn cũng có thể truy cập các thành phần công cộng. Thử nó!

Các vấn đề liên quan