1

I have 3 custom tRectangle on a form. When creating the custom tRectangle, I set CanFocus = True;, so the tRectangle can be focused. On FormCreate event, I set the TabOrder to 0 to the first tRectangle, to 1 to the second tRectangle and to 2 to the third tRectangle.

When running the application, the first tRectangle, since it's TabOrder is 0, should get the focus, but it does not.

Also, when tabbing, the second control gets focus, then the third control and at this point the focus gets stuck. Now, if tabbing with the Shift key pressed, the second control gets focus, until it reaches the first control, and again the focus gets stuck.

I appreciate if anyone can tell me why the control with TabOrder 0 is not focused at runtime and why tabbing is not acting in a circular way.

Follows code:

unit frmMyRect;
interface
uses FMX.Controls, FMX.Controls.Presentation, FMX.Forms, FMX.Layouts, 
     FMX.Objects, FMXFMX.StdCtrls, FMX.Types,System.Classes, System.UITypes;
type
  tfrmMyRect =  class (tForm)
     procedure FormCreate (Sender: tObject);
  end;
  tMyRect = class (tRectangle)
    fMyRectLabel : tLabel;
    constructor Create (aOwner : tComponent);
    procedure MyRectClick (Sender: tObject);
    procedure MyRectEnter (Sender: tObject);
    procedure MyRectExit  (Sender: tObject);
    function GetText : string;
    procedure SetText (const aText: string);
    published
      property Text : string read GetText write SetText;
  end;
var formMyRect: tfrmMyRect;
implementation
{$R *.fmx}
var MyRect1 : tMyRect;
    MyRect2 : tMyRect;
    MyRect3 : tMyRect;
procedure tformMyRect.FormCreate (Sender: tObject);
begin
  MyRect1 := tMyRect.Create (Self);
  MyRect1.Parent := frmMyRect;
  MyRect1.TabOrder := 0;
  MyRect1.Text := 'MyRect&1';
  MyRect2 := tMyRect.Create (Self);
  MyRect2.Parent := frmMyRect;
  MyRect2.TabOrder := 1;
  MyRect2.Text := 'MyRect&2';
  MyRect3 := tMyRect.Create (Self);
  MyRect3.Parent := frmMyRect;
  MyRect3.TabOrder := 2;
  MyRect3.Text := 'MyRect&3';
end; { FormCreate }
constructor tMyRect.Create (aOwner: tComponent);
begin
   inherited;
  CanFocus   :=  True;
  Height     :=   23;
  OnClick    :=  MyRectClick;
  OnEnter    :=  MyRectEnter;
  OnExit     :=  MyRectExit;
  TabStop    :=  True;
  Width      :=   80;
  fMyRectLabel := tLabel.Create (Self);
    with fMyRectLabel do begin
           Align          := tAlignLayout.Center;
           FocusControl   :=  Self;
           HitTest        :=  False;
           Parent         :=  Self;
           StyledSettings := [];
           TabStop        :=  False;
            with TextSettings do begin
                 FontColor  := TAlphaColorRec.Blue;
                 WordWrap   :=  False;
                 Font.Style := [TFontStyle.fsBold];
            end;
    end;
  end; { Create }
  procedure ctMyRect.MyRectClick (Sender: tObject);
  begin
    Fill.Color := TAlphaColorRec.Aqua;
  end;
  procedure ctMyRect.MyRectEnter (Sender: TObject);
  begin
    Fill.Color := TAlphaColorRec.Aqua;
  end;
  procedure ctMyRect.MyRectExit (Sender: TObject);
  begin
    Fill.Color := TAlphaColorRec.Beige;
  end;
  end.
user2383818
  • 709
  • 1
  • 8
  • 19
  • Assuming you are using the `tMyRect` from your previous question, how are you indicating the focused rectangle? If you are not using `tMyRect` please show code with which the problem can be reproduced. – Tom Brunberg Sep 08 '19 at 20:44
  • @Tom Brunberg Your Right. I inserted code for handling the `OnCanFocus`event, and the `tRectangle` with the `TabOrder` 0 is focused, but the `tabStop` issue remains. Any tip? – user2383818 Sep 08 '19 at 22:48
  • You really ought to provide a [reprex], so this is just pure speculation: maybe you haven't set `TabStop := True` for the first `TMyRect`. When I set both `TabOrder` and `TabStop` for three of your `TMyRect`, tabbing works as expected. If I leave `TabStop := False` for the first `TMyRect` then tabbing never goes to that rectangle, but goes 1-2-1-2-1..., so, no locking as you describe. – Tom Brunberg Sep 09 '19 at 05:43
  • @Tom Brunberg Sorry. My mistake. Follows an example: – user2383818 Sep 09 '19 at 14:09

1 Answers1

2

1. Control with TabOrder = 0 is not focused when form first appears

I can confirm this with your code and also with e.g. TEdit controls. Consider two edit controls on a form. When added to the form in the designer, the first one added got TabOrder = 0. When the form is first shown, neither has focus. After a Tab entry, the first created receives the focus.

From help for FMX.Controls.TControl.TabOrder:

TabOrder is the order in which child controls are visited when the user presses the TAB key. The control with the TabOrder value of 0 is the control that has the focus when the form first appears.

The second sentence is not correct. But the control with TabOrder = 0 will be the first to receive focus when user hits Tab key.

To assure that a specific control has focus already when the containing form appears, set:

Focused := MyRect1;

or, maybe better:

MyRect1.SetFocus;

in the forms OnCreate() event.


2. Tabbing is not acting in a circular way

After trying your code, I still cannot reproduce the problem you claim. Maybe you are just misjudging what appears to you.

Because of this line at the beginning of constructor tMyRect.Create():

Align      := tAlignLayout.Center;

all rects are on top of each other in the center of the form, IOW you can only see the top one. (Focused controls are not automagically brought to the front) Remove that line and place the rects appart (position.X and position.Y) so you can see which one is currently focused.

The line FocusControl := Self; seems misplaced (in XE7 at least), so I outcommented it.

TAB through the tMyRect controls works exactly as expected, in the order:

MyRect1 - MyRect2 - MyRect3 - Myrect1 ...

and Shift-TAB in the opposite order.

Tom Brunberg
  • 20,312
  • 8
  • 37
  • 54
  • Sorry for that Align := tAlignLayout.Center;. This is because in my application, I have three `tLayouts` already positioned on the form. On Create event, I set rects parents to the `tLayouts`, so they are correctly positioned on the form at runtime. In turn, the `tLayouts` are on a `tRectangle` (sorry, I am a bit neurotic with presentation issues). I made sure also, that only `MyRect` controls, can receive focus and respond for `Tab` key. The example has only MyRect's for the sake of simplicity. – user2383818 Sep 10 '19 at 21:27
  • It seems that the issue lies on those `tRectangle` and `tLayouts`. Somehow they interfire with the `Tab` functionality. – user2383818 Sep 10 '19 at 21:30
  • Yes, they do. Each parent arranges its own children in tab order. Each `TLayout` has as default a `taborder` according to the order they were placed on the form. If each `TLayOut` has only one control (`TMyRect`) they will all have by default `TabOrder = 0`, because they all have different parents. Now that the `TMyRect`s have different parents there's no need to set their order when you create them. Set only the order of the `TLayouts`. I will recheck this tomorrow. – Tom Brunberg Sep 10 '19 at 21:49
  • That's correct! I should have noticed that! I was so sure that I have to set `TabOrder` to `MyRect` controls, that I totally forgot that rule. The thing is that we only see our error when someone points it out for us. Thanks! I did the necessary corrections and `Tab` key works fine. – user2383818 Sep 10 '19 at 23:04