gpt4 book ai didi

delphi - 改变TEdits Delphi Xe5焦点的正确方法

转载 作者:行者123 更新时间:2023-12-02 00:10:20 26 4
gpt4 key购买 nike

我四处搜寻,一般答案似乎是这样的

SomeEdit2.setFocus;

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

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

最佳答案

您无法将 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.

关于delphi - 改变TEdits Delphi Xe5焦点的正确方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21208379/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com