2009-08-24 4 views
8

일반적으로 스윙 (또는 모든 UI) 응용 프로그램을 만들 때 메뉴 항목과 버튼에 나타나는 다양한 동작이 있습니다. 나는 보통 액션 레지스트리를 생성하고 거기에 액션을 저장 한 다음 특정 일이 발생하면 어플리케이션의 상태에 따라 레지스트리에서 액션을 비활성화/활성화합니다. 내 자신의 방법을 충분히 알고 있지만, 액션을 관리하는 데있어 꽤 전형적인 패턴입니까? 아니면 그것을하기위한보다 표준적인 방법이 있습니까?레지스트리로 스윙 동작 관리

덕분에,

제프 내 경험, 스윙 GUI에서 수행 작업을 처리하는 '가장'표준 방법에서

답변

10

Jeff, 접근 방식이 좋은 접근 방법 인 것 같습니다. 나는 똑같은 일을한다. 나는 레지스트리 ActionHandler를 호출은 다음과 같습니다

import com.google.common.collect.ClassToInstanceMap; 
import com.google.common.collect.ImmutableClassToInstanceMap; 

import javax.swing.*; 
import javax.swing.text.DefaultEditorKit; 

public class ActionHandler { 

    private static final ClassToInstanceMap<Action> actionMap = 
      new ImmutableClassToInstanceMap.Builder<Action>(). 
        put(DefaultEditorKit.CutAction.class, new DefaultEditorKit.CutAction()). 
        put(DefaultEditorKit.CopyAction.class, new DefaultEditorKit.CopyAction()). 
        put(DefaultEditorKit.PasteAction.class, new DefaultEditorKit.PasteAction()). 
        put(RefreshAction.class, new RefreshAction()). 
        put(MinimizeAction.class, new MinimizeAction()). 
        put(ZoomAction.class, new ZoomAction()). 
        build(); 

    public static Action getActionFor(Class<? extends Action> actionClasss) { 
     return actionMap.getInstance(actionClasss); 
    } 
} 

이제 비활성화 할 수는 ZoomAction, 나는 다음 반사적으로 그들을 찾는 나는 행동에 주석을 사용하고

ActionHandler.getActionFor(ZoomAction.class).setEnabled(false); 
5

ActionListener의를 생성하고이 구성 요소에 대한 직접 ActionEvent의를 처리하는 것입니다 그 (것)들은 등록된다. 그것은 단순한 디자인이며, Swing 프레임 워크 (MouseListener/MouseEvent, TableModelListener/TableModelEvent, 등)의 다른 종류의 GUI 이벤트와 규칙을 따릅니다.

사용자가 설명하는 프레임 워크는 많은 입력 방법 (예 : 툴바 버튼과 메뉴 항목을 사용하면 동일한 작업 수행)에서 발생하는 동작을 공유 할 수있는 강력한 도구입니다. 따라서 트리거 된 이벤트를 처리하기 위해 동일한 Object을 공유합니다. 두 가지 등). 이 추상화는 매우 멋지지만 Sun은 간단한 관찰자보다 조금 더 무겁다 고 강조합니다. Action JavaDoc:

주에서 그 액션의 구현은 기능과의 중앙 제어 나 프로퍼티 변경의 통지의 혜택을 제공하지 않는 일반의 ActionListener보다 저장 측면에서 더 비싼 경향이있다. 이러한 이유 때문에, 당신은 그들의 장점이 요구되는 곳에서만 액션을 사용하고 다른 곳에서는 간단한 액션 리스너를 사용하도록주의를 기울여야한다.

+0

일반적으로 내가 취하는 접근 방식은 모두 의미가 있습니다. 나는 내가 그 (것)들을 사용할 필요가있을 때 활동을 처리하기 위하여 나가 멀리 베스트를 만나는 것을 시도하고 있다는 것을 짐작한다 ... –

5

나는 일반적으로 다음과 같은 접근 방식을 취

  • 는 포함 Component의 액션 맵으로 Action을 등록합니다.
  • 는 애플리케이션 부트 스트랩 코드 (하는 JToolBar, JMenuBar 등등을 추가하는 예) 필요에 Component에서 Action 사항 "풀"할 수 있도록 공개 String 상수를 정의한다.
  • Component 내에 전용 updateActionStates() 메서드를 정의합니다.이 메서드는 사용자가 일부 작업 (예 : JTable에서 N 행 선택)을 수행 할 때 호출됩니다. 이 메서드는 Component의 현재 상태에 따라 모든 맞춤 동작을 활성화/비활성화합니다.

예 :

public class MyPanel extends JPanel { 
    public static final String MY_ACTION_NAME = "MyAction"; 

    private final JTable myTable;  

    public MyPanel() { 
    // Create action and define behaviour. 
    this.myAction = new AbstractAction(MY_ACTION_NAME, ...); 

    // Register with component's action map. 
    getActionMap().put(myAction.getValue(Action.NAME), myAction); 

    // Optionally register keyboard shortcuts using component's input map. 
    getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(...); 

    // Create JTable and add a call to updateActionStates when the selection changes. 
    myTable = new JTable(...); 
    myTable.getSelectionModel().addListSelectionListener(new ListSelectionListener() { 
     public void valueChanged(ListSelectionEvent evt) { 
     updateActionStates(); 
     } 
    }); 
    } 

    private void updateActionStates() { 
    // Action will only be enabled if one table row is selected. 
    getActionMap.get(MY_ACTION_NAME).setEnabled(myTable.getSelectedRowCount == 1); 
    } 
} 

// Application start-up code: 

MyPanel pnl = new MyPanel(); 
JToolBar toolBar = new JToolBar(); 
// Pull out action from action map and add to toolbar. 
toolBar.add(pnl.getActionMap().get(MyPanel.MY_ACTION_NAME)); 

가 덧붙여, 나는 일반적으로 내 Component의 API의 일부를 구성 Action의 노출에 대한 ActionListener s의 Action의 선호합니다. Component 내에있는 액션 (예 : 대화 상자의 '지우기'버튼)의 경우 일반적으로 ActionListener을 사용합니다. 그러나, 나는 가장 일반적인 접근 방법 인 ActionListener에 대해 동의하지 않습니다. 이것은 더 작은 GUI에서는 가능하지만 더 복잡한 스윙 응용 프로그램에서는 그렇지 않을 수 있습니다.

0

를 사용 말한다.

조금 깔끔하고 새로운 동작이 자동으로 관리됩니다.