2011-12-22 2 views
8

제 질문에 바로 접근하십시오.Java - 대규모 GUI 프로젝트 수행

어떻게 대규모 GUI 프로젝트를합니까? 지금까지 자바에서 더 큰 GUI 프로젝트를 수행하지는 않았지만 지금은 꽤 빠르게 성장하고 꽤 커졌습니다. 그리고 지금은 짜증나고 지저분한 코드 더미가 붙어 있습니다.

나는 웹 개발 분야에서 왔습니다. MVC 프레임 워크에 익숙해 져서 프로젝트에 3 개의 패키지가 있습니다. 모델은 부울 파일이나 데이터베이스와 상호 작용하는 클래스를 유지합니다.보기는 Forms 나 GUI 및 컨트롤러에 대한 클래스를 유지합니다. 패키지 어디에 내가 내 논리의 대부분을 유지.

나는 내 논리를 분리하고 다른 클래스의 한 클래스와 리스너에서 작업을 계속하도록 말되었지만 모든 것을 연결하는 방법을 알지 못합니다.

지금까지 GUI가 실행되면 어떻게되는지에 관한 모든 메소드를 실행하는 컨트롤러 클래스가 하나 밖에 없습니다.

package pft.controller; 


import java.io.IOException; 
import java.util.logging.Level; 
import java.util.logging.Logger; 
import javax.swing.JLabel; 
import javax.swing.JComboBox; 
import javax.swing.JTree; 
import java.awt.event.*; 
import javax.swing.JProgressBar; 
import pft.view.Invoke_GUI; 
import pft.model.Events; 
import pft.model.Parse; 

public class Tower_Controller { 

    public Tower_Controller() { 
    } 
    //Global variables 
    String isSelected = null; 
    int hasModules = 0; 
    int cap = 0; 
    int cpu = 0; 
    int shield = 0; 
    int armor = 0; 

    public void setName(String name){ 
     this.isSelected = name; 
    } 

    public String getName(){ 
     return this.isSelected; 
    } 

    public void setCap(int cap){ 
     this.cap = cap; 
    } 

    public int getCap(){ 
     return this.cap; 
    } 

    public void setCpu(int cpu){ 
     this.cpu = cpu; 
    } 

    public int getCpu(){ 
     return this.cpu; 
    } 

    public void setShield(int shield){ 
     this.shield = shield; 
    } 

    public int getShield(){ 
     return this.shield; 
    } 

    public void setArmor(int armor){ 
     this.armor = armor; 
    } 

    public int getArmor(){ 
     return this.armor; 
    } 


    public void invoke() throws IOException { 
     Invoke_GUI runnable = new Invoke_GUI(); 
     final JLabel tower_name = runnable.tower_name; 
     final JComboBox tower_select = runnable.tower_select; 
     final JTree module_browser = runnable.module_browser; 
     final JTree selected_modules = runnable.selected_modules; 

     final JProgressBar cap_bar = runnable.cap_bar; 
     final JProgressBar cpu_bar = runnable.cpu_bar; 

     final JLabel em_res = runnable.em; 
     final JLabel th_res = runnable.thermic; 
     final JLabel ki_res = runnable.kinetic; 
     final JLabel ex_res = runnable.explosive; 

     setTowerName(tower_name, tower_select); 
     removeTower(tower_name); 
     runnable.setVisible(true);  

    } 

    public void removeTower(final JLabel tower_name) { 
     tower_name.addMouseListener(new MouseListener() { 

      @Override 
      public void mouseClicked(MouseEvent e) { 
       if (hasModules == 1 & isSelected != null) { 
        Events evt = new Events(); 
        evt.towerHasModules(); 
       } else if (isSelected == null) { 
       } else { 
        tower_name.setText("No Control Tower selected"); 
        isSelected = null; 
       } 
      } 

      @Override 
      public void mousePressed(MouseEvent e) { 
      } 

      @Override 
      public void mouseReleased(MouseEvent e) { 
      } 

      @Override 
      public void mouseEntered(MouseEvent e) { 
      } 

      @Override 
      public void mouseExited(MouseEvent e) { 
      } 
     }); 
    } 

    public void updateVariables(String name) throws IOException{ 
     Parse tower = new Parse(); 
     String data[] = tower.towerData(name); 
     Integer x = Integer.valueOf(data[1]).intValue(); 
     setCap(x); 
    } 

    public void setTowerName(final JLabel tower_name, final JComboBox tower_select) { 
     tower_select.addActionListener(new ActionListener() { 

      @Override 
      public void actionPerformed(ActionEvent e) { 
       if (isSelected != null) { 
        Events evt = new Events(); 
        evt.towerSelected(isSelected); 
       } else { 
        tower_name.setText(tower_select.getSelectedItem().toString()); 
        setName(tower_name.toString()); 
        try { 
         updateVariables(tower_name.toString()); 
        } catch (IOException ex) { 
         Logger.getLogger(Tower_Controller.class.getName()).log(Level.SEVERE, null, ex); 
        } 
       } 
      } 
     }); 
    } 


} 

튜토리얼과 작은 일반적으로 하나의 클래스 자바 GUI 그러나 하나의 클래스보다는 조금 더 큰 프로젝트를 수행하는 방법에 대한 어떠한 튜토리얼이나 예제를 수행하는 방법 예는 많이 있습니다.

사전에 모든 도움과 조언을 주셔서 감사합니다.

+0

http://en.wikipedia.org/wiki/Mediator_pattern –

+0

도 참조하십시오 ['MVCGame'] (http://stackoverflow.com/a/3072979/230513). – trashgod

답변

6

다음은 일반적으로 스윙 개발에 대한 조언입니다. 모델의 뷰와 인터레이스의 필요를 연결하기 위해 컨트롤러를 사용하는 것이 중요하다는 점을 설명합니다.내가 다음, 프로그램 및 컨트롤러의 모델을 정의하는 봄을 사용하는 MVC 프레임 워크를 설계의 방법에 뷰에 의해 전달 된 이벤트를 묶는 컨트롤러에 주석을 사용했다

GUI guidelines for swing

마지막 스윙 프로젝트 제어 장치. 뷰는 이벤트 버스 인 이벤트 디스패처에 액세스 할 수 있었고 버스를 통해 전송 된 이벤트는 주석을 통해 컨트롤러의 메소드라고 불렸습니다. 이렇게하면 모든 컨트롤러가보기의 이벤트에 응답 할 수있었습니다. 컨트롤러가 너무 커지면 각 메소드 세트를 다른 컨트롤러로 리팩토링하는 것이 매우 쉬워졌고 뷰 또는 모델을 변경할 필요가 없었습니다.

이벤트 버스의 아름다움은 모델과 공유 될 수 있었기 때문에 모델이 컨트롤러가 등록 할 수있는 비동기 이벤트도 전달할 수있었습니다. 이 프레임 워크는 위치에 일단 우리가 일을 얻을 수있는 방법을 빨리 놀라운했다

public class SomeController { 

    private AuthenticationModel authenticationModel; 

    private LoginService loginService; 

    private MyApp view; 

    @Listener(event = "login") 
    public void login(LoginEvent event) { 
     view.showWaitDialog(); 
     loginService.login(event.getUserName(), event.getPassword()) 
     .onResult(new Callback<User>() { 
      public void onResult(User user) { 
       authenticationModel.setUser(user); 
       view.hideWaitDialog(); 
       view.showStartScreen(user); 
      } 
     }); 
    } 

} 

: 그것은 같은 것을 보았다. 그리고 우리는 기능을 추가하면서 꽤 잘 잡았습니다. 대규모 Swing 프로젝트 (3 가지)에 대한 나의 공평한 분배를 수행했으며,이 아키텍처는 큰 차이를 만들었습니다.

+0

+ 1 버스의 경우 – Bill

+0

프레임 워크가 실제로 흥미로운 것 같지만 모델 및보기에 대한 자세한 정보를 추가 할 수 있습니까? (당신의 프레임 워크를 구현하고 싶습니다.) 저는 Sterling Duchess와 같은 문제가 있지만 Spring과 java annotations에 익숙하지 않습니다. ( – AwaX

3

GUI를 확장하는 가장 쉬운 방법은 모든 것을 느슨하게 결합하는 것입니다. 이벤트 (스윙과 자신의)가 이것을 수행하는 가장 좋은 방법입니다. 클래스가 직접 GUI 요소를 만들거나 표시하지 않는 한 UI에서 다른 요소를 알거나 신경 써서는 안됩니다.

컨트롤러는 다른 이벤트에 대한 응답으로 이벤트 발생을 계속해야합니다. 그러나 이러한 이벤트는 앱의 요구에 따라 정의 된 애플리케이션 수준 이벤트 여야합니다. 컨트롤러 직접 GUI 요소를 조작해서는 안됩니다. 대신 이벤트에 관심이있는 컨트롤러에 등록한 구성 요소 (아마도 JWhatever의 하위 클래스)를 만들어야합니다.

예를 들어, nameChanged() 함수를 사용하여 TowerEventListener 인터페이스를 만듭니다. Controller에는 changeTowerName() 함수가 있으며,이 모델을 호출하면 모델 (Tower 클래스)을 업데이트 한 다음 TowerEventListeners에 대해 nameChanged()을 호출합니다.

그런 다음 예를 들어 텍스트 상자가있는 JDialog (즉, 팝업 창)와 컨트롤러에 대한 참조와 함께 OK 버튼을 포함하는 TowerRenamer 클래스를 만듭니다. 사용자가 확인을 클릭하면 Controller.changeTowerName()이 호출됩니다. TowerEventListeners으로 등록 된 GUI의 다른 부분은 필요에 따라 (UI의 JLabel을 업데이트하여) 이벤트를 수신하고 업데이트합니다.

사용자의 필요가 간단하다면 PropertyChangeEvents을 사용하고 전체 이벤트 인터페이스 구조에 대해 걱정할 필요가 없습니다. PropertyChangeSupport은 컨트롤러에서 이벤트 알림을 발생시키는 데 사용할 수 있습니다.

2

이미 제공된 훌륭한 조언 외에도 Trygve Reenskaug에 쓰여진 내용 및/또는 on his MVC page을 읽는 것이 좋습니다. 그는 70 년대 후반에이 건축 양식을 개발하는 동안 거기에있었습니다. 그의 두 페이지 기술 보고서는 1979 년 12 월의 Models - Views - Controllers에서 모델, 뷰 및 컨트롤러에 대한 가장 간결한 설명을 제공합니다. 특히 노트의

는, 뷰는 모두 관찰자조종 모델의 있습니다. 컨트롤러는 주로 뷰를 정렬 (와이어 링)하고 사용자 입력을 모델과의 상호 작용으로 변환하는 것과 관련이 있습니다. 거기에있는 여러 MVC 프레임 워크는 모델에서 뷰로 데이터를 중계하는 컨트롤러를 가지고 있습니다. 이것은 잘못된 것입니다. paper from earlier in 1979편집기의 개념을 관련보기 조합으로 포함했습니다. 편집자는 삭제되었습니다. 그 기능은 컨트롤러와 뷰 모두로 옮겨졌습니다.

이 가이드 라인을 적용하는 방법을 설명하는 데 유용한 또 다른 기사는 Burbeck's How to use Model-View-Controller입니다. 스몰 토크를 염두에두고 작성 되었기 때문에 Java로 쉽게 변환 할 수는 없지만 가이드 라인을 적용하는 방법을 잘 설명하고 있습니다.

내가 고려해야 할 가장 중요한 점은 원래 MVC 스타일이 동일한 모델의 둘 이상의보기 (표현)가 포함 된 사용자 인터페이스 용으로 만들어진 것입니다. 이 기능은 사용자 인터페이스에서는 잘 작동하지만 예외적으로 웹 서비스 세계로는 잘 변환되지 않습니다. GUI에 MVC를 사용하면이 스타일의 힘을 실제로보고 이해할 수 있습니다.