2012-04-12 3 views
7

컨트롤의 가시성을 제어하는 ​​동작을 사용하려고합니다. 내 코드는 다음과 같습니다액션을 사용하여 컨트롤의 가시성을 결정하려면 어떻게해야합니까?

파스칼 파일

unit Unit1; 

interface 

uses 
    Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, ActnList, StdCtrls; 

type 
    TForm1 = class(TForm) 
    Button1: TButton; 
    ActionList1: TActionList; 
    Action1: TAction; 
    CheckBox1: TCheckBox; 
    procedure Action1Update(Sender: TObject); 
    end; 

var 
    Form1: TForm1; 

implementation 

{$R *.dfm} 

procedure TForm1.Action1Update(Sender: TObject); 
begin 
    (Sender as TAction).Visible := CheckBox1.Checked; 
end; 

end. 

양식 파일

object Form1: TForm1 
    object Button1: TButton 
    Left = 8 
    Top = 31 
    Action = Action1 
    end 
    object CheckBox1: TCheckBox 
    Left = 8 
    Top = 8 
    Caption = 'CheckBox1' 
    Checked = True 
    State = cbChecked 
    end 
    object ActionList1: TActionList 
    Left = 128 
    Top = 8 
    object Action1: TAction 
     Caption = 'Action1' 
     OnUpdate = Action1Update 
    end 
    end 
end 

양식이 처음 버튼이 표시 실행 확인란을 선택하면. 그런 다음 확인란의 선택을 취소하면 단추가 사라집니다. 확인란을 다시 선택하면 버튼이 다시 나타나지 않습니다.

나는 이것에 대한 이유는 TCustomForm.UpdateActions에서 다음 지역 함수 내에서 발견 될 수 있다고 생각 :

procedure TraverseClients(Container: TWinControl); 
var 
    I: Integer; 
    Control: TControl; 
begin 
    if Container.Showing and not (csDesigning in Container.ComponentState) then 
    for I := 0 to Container.ControlCount - 1 do 
    begin 
     Control := Container.Controls[I]; 
     if (csActionClient in Control.ControlStyle) and Control.Visible then 
      Control.InitiateAction; 
     if (Control is TWinControl) and (TWinControl(Control).ControlCount > 0) then 
     TraverseClients(TWinControl(Control)); 
    end; 
end; 

Control.Visible의 검사가 다시 자동으로 업데이트 할 수있는 기회를 점점 내 행동을 차단하기 위해 나타납니다.

문제를 올바르게 진단 했습니까? 품질 보증 보고서를 제출해야합니까? 누구든지 해결 방법을 알고 있습니까?

+0

어째서 ['OnUpdate'] (http://docwiki.embarcadero.com/Libraries/en/Vcl.ActnList.TAction.OnUpdate)를 사용하고 있습니까? – TLama

+0

@TLama : 그것이 바로 그 때문입니다. 가장 자주, 나는 당신이'Visible'보다는'Enabled'를 설정했다고 생각합니다. –

+0

이것은 버그이거나 적어도 Misbegotten-Feature입니다. 모든 작업에 대해 Enabled 및 Visible을 설정할 수 있어야하며 연결된 컨트롤은 Enabled 값과 Visible 값을 포함하도록 새로 고쳐야합니다. 여기에 ActionUpdate가 필요한 경우 수행하려는 디커플링 종류가 중단됩니다. 이제 확인란이 작업과 결합되어야합니다. 난 단지 OnUpdate를 사용하여 표시에 대한 변경 사항을 중지하고 확인란을 onclick에서 한 줄로 표시하거나 표시하지 않도록 설정합니다. –

답변

8

진단 내용이 정확합니다. 액션은 델파이에 처음 소개 된 이래로 그렇게 작용했습니다.

의도적으로 설계된 것으로 보이지만 (아마도 보이지 않는 컨트롤의 텍스트 및 기타 시각적 요소의 과도한 업데이트를 피하기위한 최적화), 그렇다고해서 디자인이 좋은 것은 아닙니다.

영향을 줄 수있는 다른 모든 항목을 인식하지 않아도되므로 영향을받는 동작을 직접 조작하는 체크 상자 코드가 포함될 수 있습니다. 즉, OnUpdate 이벤트의 내용입니다. 너를 위해서. 확인란이 선택되면 Action1.Update으로 전화하거나 작동하지 않는 경우 Action1.Visible := True으로 전화하십시오.

대신 행동 업데이트 코드를 TActionList.OnUpdate 이벤트에 넣을 수도 있습니다.

+1

감사합니다. 놀랍습니다. 전에는 눈치 채지 못했지만 이미 문제에 대해 알고 있다는 것을 확신합니다. 내 공통 기본 클래스 형식에서 이미'TCustomForm.UpdateActions'를 재정의했습니다. 그래서 내가 원하는대로 업데이트를 수행 할 수있는 작업을 할 수 있습니다. 아마 나를위한 가장 쉬운 길입니다. –

2

관련 컨트롤이 표시되지 않으면 ActionUpdate 이벤트가 호출되지 않습니다. Checkbox1의 click 이벤트에 대해 Explicit Call ActionUpdate를 시도하십시오.

+0

"행동 사용 중지"와 같습니다. –

+0

데이비드 없음. 행동은 좋다. 그러나 Rob이 말했듯이, 그들의 디자인은 당신의 시나리오에서 사악합니다. –

+0

하지만이 문제에 대한 최선의 해결책은 GUI 컨트롤을 함께 연결할 수 없습니다. 저 지옥을 피하는 것은 내가 처음부터 행동을 사용하기 시작한 이유입니다. –

4

예. Rob이 이미 말하고 설명 한대로 진단이 정확합니다. 해결 방법은 개별 TAction의 OnUpdate 이벤트 처리기를 사용하지 않고 TActionList의 OnUpdate 이벤트 처리기를 사용하는 것입니다.

procedure TForm1.ActionList1Update(Action: TBasicAction; var Handled: Boolean); 
begin 
    Handled := True; 
    Action1.Visible := CheckBox1.Checked; 
end; 

당신은 그렇지 않으면 ACTIONLIST의의 OnUpdate 처리기 중 하나를 호출되지 않습니다 일이에 대한 링크 액션와 적어도 하나의 볼 컨트롤을 필요합니까.

Btw, 작업 및 작업 목록을 처음 소개 한 Ray Konopka (구성 요소 Raize)는 구현에 대한 몇 가지 기사를 작성하고이를 사용하는 방법에 대해 매우 건전한 조언을 제공했습니다. 그 이후로, 저는 각 개별 Action의 OnExecute를 사용하지만 ActionList의 OnUpdate를 사용하는 관행을 채택했습니다. 또한 핸들러에서 제일 먼저하는 일은 Handled를 True로 설정하여 필요 이상으로 호출되지 않도록하고 그 핸들러에서 Action의 Enabled 속성을 한 번만 변경하여 GUI가 결과로 깜박 거리지 않도록합니다 그것을 끄고 나서http://edn.embarcadero.com/article/27058 레이 (Ray Konopka)는 자신의 사이트에서 3 개의 기사를 사용했지만, 엠바 카데로 (embarcadero)에는 하나 뿐이지 만 "결합 된"버전 일 수도 있습니다. 원본을 편리하게 사용하십시오.)

+2

감사합니다. 레이 기사를 찾아 볼게. 필자는 목록에 대해 'OnUpdate'를 전혀 알지 못했지만 코드의 중앙 집중화가 좋을 것이라고 상상할 수 있습니다. –

+1

@DavidHeffernan : 예, 코드 중앙 집중식을 사용합니다. –

관련 문제