2010-03-25 3 views
4

[확인] 단추를 사용하도록 설정하기 전에 몇 가지 규칙을 충족해야하는 대화 상자에서 작업하고 있습니다.GUI 응용 프로그램에서 복잡한 규칙 처리 (C++ 또는 C#)

현재 데이터 입력이나 드롭 다운 목록에서 항목 선택과 같은 모든 작업은 ProcessEvent()라는 단일 함수를 호출합니다.이 함수는 모든 논리를 처리하고 OK 버튼을 활성화 또는 비활성화합니다 .

내 문제는 규칙을 간결하고 이해하기 어렵게 만드는 것입니다.

규칙 중 일부는 대화 상자의 다른 작업에 의해 무효화 될 수 있으며, 다른 곳의 진술이나 읽지 못하고 뒤 따르기가 어려울 때 끝납니다. &.

아래의 코드는 문제의 단순화이지만 잘 보여줍니다. 나는 그것은 국가 시스템과 규칙을 제정하려고하는 데 도움이,하지만 그 실제의 경우 그 성격에 따라 수

bool CWorkstation::ProcessEvent(void) 
    { 
     UpdateData(); 

     CharCount = GetDlgItemInt(IDC_CharCount, NULL, FALSE); //get latest 

     if (IsDlgButtonChecked(IDC_USEDBNAME)) 
      { 
       if (!IsDlgButtonChecked(IDC_MAXDBNAME)) 
        { 
         EnableNext(TRUE); 
        } 
      } 

     if (IsDlgButtonChecked(IDC_MAXDBNAME) && CharCount) 
      {     
       if (IsDlgButtonChecked(IDC_USEXMLNAME)) 
        { 
         if (PrefixName.IsEmpty()) 
          { 
           EnableNext(FALSE); 
          } 
         else 
          { 
           EnableNext(TRUE); 
          } 
      } 



      } 


     if (IsDlgButtonChecked(IDC_USEXMLNAME) && PrefixName.GetLength() > 1) 
      { 
       EnableNext(TRUE); 
      } 



     if (IsDlgButtonChecked(IDC_WSAUTONAME) || IsDlgButtonChecked(IDC_RENAMEIFDUP)) 
      { 

      // TRACE("IDC_WSAUTONAME is Checked\n"); 

      if (IsDlgButtonChecked(IDC_USEXMLNAME) && PrefixName.GetLength() > 1) 

       { 


       if (IsDlgButtonChecked(IDC_IDC_USESHORTNAME)) 

        { 

        EnableNext(TRUE); 
        } 

       else if (IsDlgButtonChecked(IDC_USELONGNAME)) 

        { 

        EnableNext(TRUE); 

        } 

       else 

        { 
        EnableNext(FALSE); 
        } 



       } 


      if (!IsDlgButtonChecked(IDC_USEPREFIX)) 

       { 


       if (IsDlgButtonChecked(IDC_IDC_USESHORTNAME) || IsDlgButtonChecked(IDC_USELONGNAME)) 

        { 
        EnableNext(TRUE); 
        } 

       } 


      return false; 


      } 

     } 

답변

6

if/else 문을 여러 함수로 분할하고 EnableNext로 보내는 매개 변수에 & =을 사용합니다. EnableNext를 한 번만 호출해야합니다.

따라서, 예를 들어 :

// in CWorkStation::ProcessEvent 
bool enableNext = true; // start with true 

enableNext &= Condition1(); // of course pick better names than Condition1 
enableNext &= Condition2(); // this is just for an example 

EnableNext(enableNext); 

조건 1은() 수 있습니다 장소 : 등등

bool Condition1() 
{ 
    return (IsDlgButtonChecked(IDC_USEDBNAME) 
     && !IsDlgButtonChecked(IDC_MAXDBNAME)); 
} 

그리고있다.

여기서 발생하는 것은 enableNext 변수가 true로 시작한다는 것입니다. 그런 다음 각각의 & = 당신은 어떤 ConditionX() 함수가 false를 반환하면 enableNext가 false로 끝난다는 것을 의미합니다. 모든 조건이 참이면 끝날 때만 사실입니다.

+1

좋아요. 이제 "& ="가 무엇인지 정확하게 알아 내야합니다. – Canacourse

+0

아 예. & =는 논리 바로 가기 연산자입니다. enableNext = EnableNext = && Condition() 글쎄, 기술적으로는 enableNext = enableNext & Condition1()이지만, bool의 경우에는 사실상 똑같습니다. 게시하려면 편집을 참조하십시오. –

+1

작은 메모 : && = 연산자가 없으므로 Condition1()이 항상 & =와 함께 호출되므로주의해야합니다. 함수에 부작용이 없으면 잘 작동하지만 상태가 바뀌면 예상치 못한 결과가 발생할 수 있습니다. – Macke

0

이 문제가 더 나은 (만약의 가능성을) 처리합니까. 이러한 접근 방식에서 사용자가 대화 상자의 일부 필드를 채우거나 확인란을 선택하면 상황에 맞는 컴퓨터의 상태가 그에 따라 업데이트됩니다. 가지고있는 경우 Boost.Statechart을 사용하여 구현할 수 있습니다.

0

그런 경우에는 기본적으로 버튼을 활성화하여 가능한 한 간단하게 만드는 경향이 있으며 다른 조건이 설정되어 있으면 (또는 설정하지 않은 경우) 비활성화하십시오. 이것은 "if"조건에서 "else"와 다른 경우를 제한합니다.

1

이 문제는 청취자의 개념으로 해결할 수 있습니다.

GUI 구성 요소 각각에 isEnabled() 메서드를 만들 수 있습니다.이 메서드는 일부 조건에 따라 조건을 확인합니다. isEnabled()은 구성 요소의 상태를 변경하는 조치가 호출 될 때 각 GUI 구성 요소에서 호출됩니다. 다음과 같은 선언을 할 수 있습니다

이 방법 : 당신의 GUI 구성 요소를 만들 때

bool CheckBoxComponent::isValid() { 
    return isNameFilled() && isEmailChecked(); 
} 

bool OkButton::canSend() { 
    return checkBoxName->isValid() && isEmailChecked(); 
} 

그런 다음, 당신은 그들 각각의 리스너를 통해 서로 연결합니다.

이렇게하면 각 구성 요소가 속한 각 구성 요소에 대한 규칙이 생기며 if 문이 많지 않습니다.

+0

'Observer'패턴을 실제로 없앴다. 이벤트를 처리 한 다음 객체의'notify' 메소드를 사용하여 등록 된 모든 Observers에게 알립니다. –

0

조건을 적절한 부울 문으로 다시 쓰고 모든 조건을 들여 쓰고 설명을 추가하십시오. IMHO, 일회용 방법으로 실제 수표를 숨겨서는 안됩니다. 당신이 코드를 주석을 언급하지만, 그 목적을위한 방법을 생성하지 않는하려는 경우, 그것은 단지 일을 모호하게하고 조건은 간단하지 않습니다

EnableNext( 
     // condition 1 
     IsDlgButtonChecked(IDC_USEDBNAME) && !IsDlgButtonChecked(IDC_MAXDBNAME) 
     // condition 2 
    || IsDlgButtonChecked(IDC_MAXDBNAME) && CharCount 
     && IsDlgButtonChecked(IDC_USEXMLNAME) && !PrefixName.IsEmpty() 
     // condition 3 
    || IsDlgButtonChecked(IDC_USEXMLNAME) && PrefixName.GetLength() > 1 
     // and so on 
) 

즉시 분명하게이 방법 당신이 것처럼 보인다 동일한 조건을 두 번 확인하십시오 USEXMLNAME && !PrefixName().IsEmpty(). 현재는 EnableNext이 항상 호출된다는 것도 분명합니다.

+0

좋은 지적. 내가 제안 할 한 가지는 여전히 로컬 enableNext와 별도의 & =를 사용하는 것입니다. 예를 들면 인라인 조건을 사용하는 것입니다. 디버거에서이 방법을 사용하면 어떤 조건으로 인해 디버거를 사용할 수 없는지 알 수 있습니다. –

+0

때때로 디버깅에 유용 할 수 있습니다. 조심하되 &는 논리 연산자가 아니라 비트 연산자입니다. – Sebastian

0

솔루션의 비트가 원하는 것보다 약간 클 수도 있지만 Adobe의 Adam and Eve 라이브러리를 살펴 보는 것이 좋습니다. Eve는 위젯 레이아웃을 다루며, Adam은 위젯의 로직에 관한 일련의 선언문을 가져와 해당 로직을 기반으로 위젯을 활성화하거나 비활성화하는 컨트롤러에 넣고 초기화를 처리하고 결과를 적절한 변수에 넣습니다 (예 : 사용자가 "확인"을 클릭 할 때).

관련 문제