2009-07-13 2 views
8

이것은 초보자가하는 질문 일지 모르지만 나는 내 인생을 생각할 수 없다.Flex에서 강제로 화면을 업데이트합니까?

저는 큰 프로젝트, 특히 하단의 상태 표시 줄에 대한 GUI를 개발할 때 flex를 사용하고 있습니다. 내 StatusBar 클래스에는 ProgressBar가 있습니다.이 클래스는 작업을 수행하는 다른 클래스가 진행할 때 업데이트 (바 완료 및 레이블 변경)를 지시 할 수 있습니다. 나는이 발생하고있어 문제는 화면에 표시 뭐죠 너무 늦기까지 플렉스 예를 들어, 업데이트되지 것입니다

ProgressBar를 초기화 0 %
수행 일부 클래스는 12 % 완료로 ProgressBar를 설정합니다
일부 클래스는 몇 가지 작업
일부 클래스는 일이 뭐죠 결코 표시되지 수행 한 12 %, 그것은 단지에 달려있다 56 %가

을 수행 할 ProgressBar의를 설정하지 작업 중 0 %를 수행 한 다음 56 %로 건너 뜁니다. 플렉스 구성 요소 (유효성 검사 및 유효성 검사)의 수명주기를 이해하려고 시도했는데이를 이해하고 올바르게 적용하고 있다고 생각하지만 전혀 작동하지 않습니다. 일부 클래스이 12 % 완료되도록 설정 한 후 일부 클래스이 작업을 시작하기 전에 Flex에 내 상태 표시 줄 (또는 적어도 내부의 ProgressBar)을 다시 그리도록 지시해야합니다. 어떻게해야합니까?

+0

이 문제는 * Flex가 화면을 업데이트 할 수 있도록 허용해야합니다. 아래에서 지적한 것처럼 Flash는 코드에 대한 단일 스레드 실행 모델입니다. 따라서 작업을 청크 처리하여 플레이어가 청크 사이에서 디스플레이를 새로 고칠 수 있도록해야합니다. callLater() 또는 타이머를 사용하여 자신을 청크 제어하는 ​​기본 메커니즘을 사용할 수 있습니다. 이 작업을 수행하지 않으면 브라우저가 45 초 후 Flash Player를 종료 할 가능성이 있음을 염두에 두십시오 (FF 기본값) – verveguy

답변

2

진행률 표시 줄을 변경할 때마다 invalidateDisplayList()를 호출 해보십시오. 뭔가 같은 :

Class StatusBar 
{ 

    public function set progress(value:uint):void 
    { 
     progressBar.value = value; 
     progressBar.invalidateDisplayList(); 
    } 
} 

Flex에는 속성이 변경 될 때마다 화면이 다시 그려지지 않는 유효성 검사주기가 있습니다. 예를 들어, 속성의 값이 단일 프레임에서 3 번 변경되면 마지막 값으로 만 렌더링됩니다. invidateDisplayList()를 호출하면 (자), 컴퍼넌트를 재 draw 할 수 있습니다. 즉, 다음의 프레임을 대기하는 대신에 updateDisplayList가 즉시 실행됩니다.

+1

실제로 "즉시"updateDisplayList()를 호출하지 않지만 다음 번에 호출합니다 화면 업데이트/프레임. 그것이 즉시 수행한다면 무효화/유효성 확인 모델의 요점을 무력화시킬 것입니다. –

+0

내 잘못이야, 넌 절대적으로 옳다. invalidateDisplayList()를 호출하는 대신 직접 updateDisplayList()를 호출해야합니다. –

2

브라우저의 자바 스크립트와 마찬가지로 Flash Player의 액션 스크립트는 의사 다중 스레드입니다. 즉, 단일 스레드이지만 여러 실행 스택이 있습니다. 즉, 특정 스레드에서 "잠"수 없지만 나중에 실행될 때까지 지연되는 새 실행 스택을 생성 할 수 있습니다. 이 작업을 수행하는 유연한 방법은 "callLater"기능입니다. setTimeout/setInterval 함수를 사용할 수도 있습니다. 또는 플래시 플레이어에 내장 된 타이머 개체를 사용할 수 있습니다. 심지어 "ENTER_FRAME"이벤트 리스너. 이 모든 것들이 근본적으로 당신이 원하는 것을 할 수있게 해줄 것입니다, 만약 내가 당신의 문제의 원인에 대해 정확하다면.

대부분의 작업을 수행하는 하나의 "스레드"가 있고 다른 실행 스택 (스레드 *)이 실행되는 것을 멈추지 않는 것처럼 들립니다.

문제는 PeZ가 말하는 것일 수 있지만, 도움이되지 않으면 작업자 클래스에 대한 지연 호출을 시도하는 것이 좋습니다. 따라서 이제 프로세스가 다음과 같이 보일 수 있습니다.

  1. 진행률이 초기화되었습니다.
  2. 일부 작업을 수행하십시오.
  3. 진행률 표시 줄을 12로 업데이트하십시오 (표시 목록을 무효화)
  4. setTimeout (doMoreWork, 100);
  5. 진행률 표시 줄을 52로 업데이트하십시오.

(사용자가 UIcomponent 인 경우 uicomp.callLater (...)를 사용할 수 있습니다. 그렇지 않으면 순수 AS3 클래스에 setTimeout/timer/enter_frame을 사용해야합니다.)

9

다른 답변에서 언급했듯이 플래시 플레이어는 단일 스레드이므로 별도의 "프레임"에서 실행될 수있는 개별 청크로 작업을 분해하지 않으면 플래시 플레이어가 단일 스레드로 점프 및 스터 터를 보게됩니다. 당신이보고있는 것입니다.

실제로 12 % 메시지가 표시되어야하는 경우 표시 목록을 무효화하는 것만으로는 충분하지 않습니다. 56 % 작업이 완료 될 때까지 표시 목록이 업데이트 될 기회가 없으므로 명시 적으로 메시지가 설정된 후 validateNow()으로 전화를 걸어 자연스러운 이벤트 사이클을 시작하십시오.

그러나 성능에 문제가있는 경우 최선의 방법은 아닙니다. 사법 용으로 callLater()을 차례로 사용하여 각 작업 청크 일정을 예약하면 플레이어가 프로세스의 다음 단계를 시도하기 전에 프레임주기를 완료하고 표시 목록을 업데이트 할 수 있습니다. 모든 플렉스에서 스레딩 무엇이든지 어떻게 작동되지 않습니다

+0

여전히 얻을 수 없습니다. invalidateDisplayList()를 호출하고 바로 validateNow()가 호출되며 업데이트되지 않습니다. 내 StatusBar 클래스뿐만 아니라 ProgressBar 및 ProgressBarSkin 무효화되고 유효성이 검사되고, 그것은 모든 방법을 간다 및 심지어 실제로 ProgressBar 채워진 부분을 다시 그리기 위해 drawRect(), 여전히 실제로 업데이트하지 않습니다. 화면. –

+1

내가 제안한 것처럼 callLater, setTimeout 또는 이와 비슷한 시도를 했습니까? 처리로 인해 렌더러가 화면을 업데이트하지 못하는 것 같습니다. 멈추고 숨을 쉬어야합니다. – Glenn

+0

아하! 기괴한 이야기, setTimeout (doWork, X)이 X보다 적게 걸린 후에 함수의 나머지 부분을 실행할 시간이 길다면 setTimeout을 사용하여 업데이트 할 수 있습니다. 즉 플래시를 보내야합니다. idle (25ms 이상). 그러나 내가 잘못된 위치에 중단 점을 넣거나 코드를 단계별로 실행하면 중단됩니다. –

3

글렌,

. 많은 UI와 마찬가지로 메인 UI 스레드에 메시지 펌프가 있습니다 (프레임에서 수행). 을 호출하면 callLater()은 전달 된 함수 포인터를 (다음 프레임의) 메시지 펌프 대기열 끝에 넣고 즉시 반환합니다. 그런 다음 메시지 펌프가 마우스 클릭과 같이 모든 메시지 처리를 완료하면 함수가 호출됩니다.

문제는 속성 변경으로 인해 UI 이벤트가 트리거되므로 사용자가 여기에 배치 한 메서드 호출 이후에 자신의 메시지를 펌프에 배치합니다 (callLater()).

Flex에는 스레드가 여러 개 있지만 Adobe의 고유 한 이유로 여기에 있으며 사용자가 액세스 할 수 없습니다. 특정 시점에 UI 업데이트가 발생하도록 보장 할 수있는 방법이 있는지 모르겠지만 옵션은 callLater에 작업이 발생할 때까지 여러 번 호출하는 것입니다. 적은 수로 시작하여 반복 횟수가 원하는 결과를 얻을 때까지 증가시킵니다. 예 :

// Change this to a number that works... it will probably be over 1, depending on what you're doing. 
private const TOTAL_CALL_COUNT:int = 5; 

private var _timesCalled:int = 0; 

//---------------------------------------------------------------- 
private function set Progress(progress:int):void 
{ 
    progressBar.value = progress; 
    DoNextFunction(); 
} 

//---------------------------------------------------------------- 
private function DoNextFunction():void 
{ 
    if(_timesCalled >= TOTAL_CALL_COUNT) 
    { 
     _timesCalled = 0; 
     Function(); 
    } 
    else 
    { 
     _timesCalled++; 
     callLater(DoNextFunction); 
    } 
} 
+0

당신은 내 반응을 오해하고 있습니다. Flex가 아닌 AS3/Flash를 주로 사용했습니다. "callLater"는 그 위에있는 Flex 구현물입니다. 백그라운드에서 작업하려면 ENTER_FRAME과 같은 이벤트를 사용하기 만하면됩니다. – Glenn

+1

setTimeout에 대한 callLater를 사용하지 않으면 AS3에서 작동합니다. –

0

저는 Flash Builder 4.6을 사용하고 있으며 진행률 표시기에 문제가 있습니다. 새로운 multiloader 클래스 (39Mo의 내용)를 시작하는 새 창을 엽니 다. 새 창은 백그라운드에서 열리고 주 창에는 다중로드 클래스가 작업을 마칠 때까지 진행률 막대가 표시됩니다. 그러나 시작 창이 내 메인 창의 애니메이션을 차단하고 있습니다. 그것이 올바르게 작동하는 것을봤을 때 multiloader 클래스가 아니라는 것을 알고 있습니다.

그러나 나는 그것을하는 몇 가지 새로운 방법을 찾으려고 노력할 것입니다.

내 게시물의 주된 목적은 어도비가 플래시 주변에 구축 한 복잡성입니다. 자신의 응용 프로그램에 대한 ressources를 찾거나 질문에 대한 대답을 찾으면 좋은 ressource를 찾는 것이 정말 고통 스럽습니다. AS3, Flex, Flash CS, Flash Builder, AiR, ... 사이에 총 혼합 (어도비 측과 사용자 측)이 있습니다. AS3에서 개발하려고하면 일부 예제가 작동하지 않습니다. SDK에 구현되어 있지 않기 때문에. 당신은 다른 개발 플랫폼에서의 경험을 바탕으로 "모범 사례"또는 아이러니 한 답변을 제공하는 포럼이 점점 더 많아지고 있습니다.

예를 들어, 위의 예에서 progressBar.value = value; 내 경험에 비추어 볼 때, Flash Builder 4.6에서이 속성은 읽기 전용이라고 말할 수 있습니다. 하지만 그것은 사용자가 만든 사용자 지정 클래스 일 수 있지만 누가 말할 수 있습니다.

1

때때로 다른 값을 지정하기 전에 0으로 설정해야합니다. progressBar.setProgress (0, progressBar.maximum); progressBar.setProgress (newValue, progressBar.maximum);

관련 문제