【问题标题】:Proper way to change focus of TEdits Delphi Xe5改变TEdits Delphi Xe5焦点的正确方法
【发布时间】:2014-01-18 18:47:09
【问题描述】:

我已经四处搜索,一般的答案似乎是

SomeEdit2.setFocus;

在 SomeEdit1.OnExit 事件中。我试过这个(使用 Delphi Xe5,为 iOS 开发),它会导致应用程序崩溃。该应用程序不会抛出错误,它只是空白并崩溃。我尝试在其他事件中放置相同的代码,但它没有按预期工作。例如,当放置在 SomeEdit1.OnChange 事件中时,当用户在虚拟键盘上点击“完成”时 - 焦点切换到所需的控件,但键盘不显示并停止正常工作。

当用户点击虚拟键盘上提供的“完成”按钮时,在控件之间更改焦点的正确方法是什么?

【问题讨论】:

    标签: delphi focus firemonkey delphi-xe5


    【解决方案1】:

    您无法将 VCL-Control 行为与 FMX-Control 行为进行比较,因为有时它们的行为不同 - 它们不应该,但它们确实如此。

    在 VCL 中,您有一个 OnExit 事件,它在焦点离开控件后立即发生。所以这是一个OnAfterExit 事件。

    在 FMX 中,OnExit 事件焦点消失之前触发。所以这是OnBeforeExit

    procedure TControl.DoExit;
    begin
      if FIsFocused then
      begin
        try
          if CanFocus and Assigned(FOnExit) then
            FOnExit(Self);
          FIsFocused := False;
    

    现在,这与您当前的问题有什么关系?

    如果您将焦点设置到OnExit 事件中的另一个控件,则会调用当前活动控件DoExit 方法,该方法调用OnExit 事件,并且您有一个完美的圆圈。

    所以你有几个选项来解决这个问题

    错误报告

    最佳解决方案是创建一个错误报告并让 emba 修复此问题。

    已经有一个错误报告117752 具有相同的原因。所以我将解决方案作为评论发布。

    补丁FMX.Controls.pas

    FMX.Controls复制到您的项目源目录并修补错误代码(仅一行)

    procedure TControl.DoExit;
    begin
      if FIsFocused then
      begin
        try
          FIsFocused := False; // thats the place to be, before firering OnExit event 
          if CanFocus and Assigned(FOnExit) then
            FOnExit(Self);
          //FIsFocused := False; <-- buggy here
    

    SetFocus控制

    要在OnExit 中设置焦点,您必须做更多的工作,因为将焦点更改为下一个控件的消息已经排队。您必须确保对所需控件的焦点更改发生在已经排队的焦点更改消息之后。最简单的方法是使用计时器。

    这是一个带有 3 个编辑控件的示例 FMX 表单,每个控件都有一个 OnExit 事件

    unit MainForm;
    
    interface
    
    uses
      System.SysUtils, System.Types, System.UITypes, System.Classes, System.Variants,
      FMX.Types, FMX.Graphics, FMX.Controls, FMX.Forms, FMX.Dialogs, FMX.StdCtrls,
      FMX.Edit;
    
    type
      TForm1 = class(TForm)
        Edit1: TEdit;
        Edit2: TEdit;
        Edit3: TEdit;
        EnsureActiveControl_Timer: TTimer;
        procedure EnsureActiveControl_TimerTimer(Sender: TObject);
        procedure Edit1Exit(Sender: TObject);
        procedure Edit2Exit(Sender: TObject);
        procedure Edit3Exit(Sender: TObject);
      private
        // locks the NextActiveControl property to prevent changes while performing the timer event 
        FTimerSwitchInProgress: Boolean;
        FNextActiveControl: TControl;
        procedure SetNextActiveControl(const Value: TControl);
      protected
        property NextActiveControl: TControl read FNextActiveControl write SetNextActiveControl;
      public
    
      end;
    
    var
      Form1: TForm1;
    
    implementation
    
    {$R *.fmx}
    
    procedure TForm1.Edit1Exit(Sender: TObject);
    begin
      NextActiveControl := Edit3;
    end;
    
    procedure TForm1.Edit2Exit(Sender: TObject);
    begin
      NextActiveControl := Edit1;
    end;
    
    procedure TForm1.Edit3Exit(Sender: TObject);
    begin
      NextActiveControl := Edit2;
    end;
    
    procedure TForm1.EnsureActiveControl_TimerTimer(Sender: TObject);
    begin
      EnsureActiveControl_Timer.Enabled := False;
      FTimerSwitchInProgress := True;
      try
        if (Self.ActiveControl <> NextActiveControl) and NextActiveControl.CanFocus then
          NextActiveControl.SetFocus;
      finally
        FTimerSwitchInProgress := False;
      end;
    end;
    
    procedure TForm1.SetNextActiveControl(const Value: TControl);
    begin
      if FTimerSwitchInProgress 
      or (FNextActiveControl = Value) 
      or (Assigned(Value) and not Value.CanFocus) 
      or (Self.ActiveControl = Value) 
      then
        Exit;
    
      FNextActiveControl := Value;
      EnsureActiveControl_Timer.Enabled := Assigned(FNextActiveControl);
    end;
    
    end.
    

    【讨论】:

    • 救命稻草!!!我刚刚尝试使用 Timer 方法,它就像一个魅力!鲁弗爵士,您非常感谢!感谢您的及时回复以及您在回答中付出的详细和努力!
    • 请注意:此错误似乎已在 XE7 中修复,因为 Rufo 爵士建议的代码更改出现在 FMX.Controls.pas 中。
    猜你喜欢
    • 1970-01-01
    • 2013-10-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-05-01
    • 1970-01-01
    相关资源
    最近更新 更多