【问题标题】:Set Focus back on edit after tab on Delphi xe2在 Delphi xe2 上的选项卡后将焦点重新设置为编辑
【发布时间】:2013-11-08 12:45:41
【问题描述】:

我有7个用户可以输入数字的编辑,数字必须在1100到1500之间。开始时,第一个编辑是焦点,用户输入他的数字,然后他推动标签聚焦到下次编辑...

我的程序必须验证用户输入的数字,如果它不满足条件(1100

我在 Edit1Change 上尝试过这段代码,但它不起作用

If (1500 < (strtofloat(edit1.text)) or (strtofloat(edit1.text) <1100) then
begin
  Showmessage ('my message');
  edit1.setfocus
end;

更新

对不起各位,我对问题的描述不是很清楚,而且我的英语也不是很好。

比较或检查条件我没有问题,我的问题是当我按TAB选择下一个编辑时,即使条件不满足,我的消息也会出现,Edit1.Text被重置为0 并且光标移动到下一个编辑控件。我想要的是当用户按下 Tab 并且输入的数字不满足条件时,出现消息,Edit1.Text 取 0 并且光标停留在 Edit1 上。

我尝试在Edit1.OnExit 中放置对条件的检查和将焦点放在同一编辑的指令,但它不会正常工作,总是当用户在输入不满足的数字后按 Tab 时条件,消息出现,第一个 Edit 取 0,光标移到下一个 Edit。

【问题讨论】:

  • 1) “不起作用”是什么意思? 2)您可以使用任何现成的组件来输入已经检查最小值和最大值的数字 3)您可以使用任何现成的库来验证输入并标记错误的条目
  • 不能再同意了。有TSpinEdits之类的,为什么还要依赖TEdits?此外,OnChange 事件也不适合这样做,因为当用户通过鼠标单击或 Tab 离开编辑组件时它不会触发。
  • @GünthertheBeautiful 单独使用 OnExit 也存在问题:当通过 ENTER 或 ESC 键关闭对话框时它不起作用 - 当焦点实际上没有进一步传递而只是关闭了表单时。或者当 TPageControl 选项卡被切换或通过单击 TSpeedButton 或 TMenuItem 关闭对话框时 - 事件无法重新设置焦点,因为 TEdit.Parent 已经不可见。所以应该更好地依赖一些表单范围的验证框架
  • @user29 :我的答案如何捕捉tab 按下的键。 Event for tab
  • 谢谢,选项卡事件的链接对我帮助很大,解决方案是将检查条件和指令(edit1.setfocus)放在下一次编辑的键上; )

标签: delphi delphi-xe2 setfocus


【解决方案1】:

这是一个老问题,但我看不到正确答案:

在焦点发生变化时,切勿操纵焦点。 在 OnExit 窗口中开始移动焦点但尚未完成。 如果您想因验证而中断焦点更改,请使用“Abort;”

procedure Txy.OnExit()
begin
 if not Validate then
   Abort;
end;

还要确保您没有在 OnClose 事件中操纵焦点 因为它最终会触发活动控件的不需要的 OnExit。

【讨论】:

    【解决方案2】:

    然后他按下标签以聚焦到下一个编辑

    那被OnExit事件http://docwiki.embarcadero.com/Libraries/XE2/en/Vcl.Controls.TWinControl.OnExit拦截

    在 Edit1Change 上尝试了此代码,但它不起作用

    “不工作”是什么意思?

    它确实有效 - 它不断地将焦点集中在您正在键入文本的编辑上。 然而,这是检查更改的糟糕时机:当用户“1100”到“1500”时,用户很可能有“100”或“15100”的中间结果,您的应用程序会通过模式对话框使他的工作崩溃。

    您应该避免在编辑时检查,只在编辑完成后检查。或者您应该以不干扰的非模态方式显示检查结果,以便用户继续编辑。就像在红色和绿色之间改变 TEdit 的背景,或者喜欢使用一些验证器库来添加错误标记。

    或者只是使用带有这些最小值、最大值和内置检查的数字编辑器

    【讨论】:

      【解决方案3】:

      导航键(Tab、BackTab、箭头键等)不受 KeyPreview 的影响,因为它们不会生成键盘事件。
      唯一指向这一事实的地方。 Delphi Help TCustomForm.KeyPreview

      您可以使用的唯一事件是下一个或上一个 TEdit 的 KeyUp 事件。

      看这里的例子:回复Intercept TAB key in KeyPress event

      【讨论】:

        【解决方案4】:

        虽然您没有具体说明什么不起作用,但特此提供一些关于为什么不起作用的答案,因为很明显您想要什么。典型用途是输入注册密钥。

        • 您使用StrToFloat 将编辑文本转换为数值。由于您希望该值介于 11001500 之间,因此您应该使用 StrToInt,尽管这不是必需的。但是这个函数的使用有一个问题,因为空编辑的Text属性是'',不能转换成数字,会导致EConvertError异常,很容易避免。使用TryStrToIntStrToIntDef 来防止出现此错误。

        • 您的条件表达式具有误导性。而不是

          if (1500 < A) or (A < 1100) then
          

          使用

          if (A < 1100) or (A > 1500) then
          

          更具可读性。您还可以使用System.Math 单元中的InRange 函数:

          if not InRange(A, 1100, 1500) then
          

          随你喜欢。

        • 您在编辑中的每次击键时检查此条件,因为OnChange 会在每次编辑时触发。现在,当您通过键入 1 开始输入正确的数字时,条件将被评估为真,(将弹出消息(但我知道这是一个临时调试功能)),编辑将是设置重点。但它已经是,所以这是不必要的。

        • 当您通过按 TAB 选择下一个编辑控件时,OnChange 事件将不会触发,因为除了失去焦点之外没有任何变化。解决方案是检查OnExit 事件中的条件。这也是前面那句话的解决方法。

        • 依赖OnExit 中的验证的一个缺点是在对话框关闭的情况下可能不会触发该事件。但这可能会或不会成为问题,因为使用 ESC 或对话框的关闭按钮退出对话框通常表示您正在取消操作。但请记住。

        奖金

        这是一个直观的实现,可以解决各种问题。将所有这些事件处理程序链接到所有编辑控件:

        const
          MinValue = 1100;
          MaxValue = 1500;
        
        procedure TForm1.EditChange(Sender: TObject);
        var
          Edit: TEdit absolute Sender;
        begin
          if Length(Edit.Text) = 4 then
            SelectNext(Edit, True, True);
        end;
        
        procedure TForm1.EditEnter(Sender: TObject);
        var
          Edit: TEdit absolute Sender;
        begin
          Edit.SelStart := Length(Edit.Text);
        end;
        
        procedure TForm1.EditExit(Sender: TObject);
        var
          Edit: TEdit absolute Sender;
        begin
          if not InRange(StrToIntDef(Edit.Text, -1), MinValue, MaxValue) then
            Edit.SetFocus;
        end;
        
        procedure TForm1.EditKeyDown(Sender: TObject; var Key: Word;
          Shift: TShiftState);
        var
          Edit: TEdit absolute Sender;
        begin
          if (Edit <> Edit1) and (Length(Edit.Text) = 0) and (Key = VK_BACK) then
          begin
            Edit.OnExit := nil;
            SelectNext(Edit, False, True);
            Edit.OnExit := EditExit;
          end;
        end;
        

        您还可以将 NumbersOnly 属性设置为 True,这将在有人尝试输入字母字符时导致 Windows 警告气球。

        反射

        OnExit 中单独验证每个编辑会给用户带来麻烦。当用户想要或想要中止操作时,无论出于何种原因,他都无法这样做,因为在他输入有效数字之前无法到达取消按钮。另一个示例情况是部分输入第二个值,并希望返回到前一个值进行更正。

        请勿以此类不便的方式骚扰用户。相反,之后验证所有值。中间失效可以通过使用颜色、星号、感叹号、图标等在视觉上发出信号......

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2019-10-31
          • 1970-01-01
          • 1970-01-01
          • 2023-03-17
          • 1970-01-01
          • 1970-01-01
          • 2012-02-05
          相关资源
          最近更新 更多