我可以将TTabItem添加到TTabControl,可以将TTabItem的子类添加到TabControl,但是不能将TTabItem的子类添加到TabControl。
Firemonkey应用程序示例-具有TTabControl的表单:
type
TTabItem_subclass = class (TTabItem);
TTabItem_sub_subclass = class (TTabItem_subclass);
procedure TForm1.FormCreate(Sender: TObject);
procedure add_tab (t: TTabItem);
begin
t.Text := t.ClassName;
t.Parent := TabControl1
end;
begin
add_tab (TTabItem.create (TabControl1)); // <-- works
add_tab (TTabItem_subclass.create (TabControl1)); // <-- works
add_tab (TTabItem_sub_subclass.create (TabControl1)); // <-- fails
end;
运行该应用程序时,TTabItem_sub_subclass不显示:
我在XE5和东京都尝试过,结果相同。我想念什么?
答案 0 :(得分:0)
简短的回答:我认为您没有丢失任何东西。实际上,您的代码确实成功地将子类别的项目添加到TabControl中,只是没有显示出来。我认为此问题是由FMX代码派生用于绘制类的样式的方式引起的,该类是TTabItem的子子类。我对FMX的了解不足,无法确定问题的确切原因,但我已经确定了似乎可以解决此问题的方法。
请参阅下面的示例项目代码,该代码成功显示了两者 TabItem子类和TabItem子_子类选项卡。
按原样构建代码的原因是,可以轻松地在其上设置更改的内存断点
TabItem的FResourceLink字段(代码中的变量Item
),而我当时
试图追踪绘画过程的发生方式。
通过查看TabItem.Paint方法,很明显该选项卡只会绘制
如果其FResourceLink不为零。您原始代码(和我的代码)的问题
是当在TabItem_subClass上调用Paint
时,其FResourceLink 已已分配
一个值,而对于TabItem_sub_subClass,它不。显然,FResourceLink
在此处获取用于绘制TabItem的样式的名称,如果
无法找到TabItem不会被绘制。
恐怕由于我不是FMX专家,我发现它的代码有些迷宫 在最佳时机,样式的实现更是如此。但它 令我震惊的是,如果我可以确保返回有效的样式名称, TabItem GetParentClassStyleLookupName方法,就足够了。那就是原因 TCustomItem_sub_subclass.GetParentClassStyleLookupName覆盖。我想 FMX专家可能会认为它像是一把大锤,可以裂开核桃,但是在那里 你去。
代码
type
TForm1 = class(TForm)
TabControl1: TTabControl;
StyleObject1: TStyleObject; // ignore this
procedure FormCreate(Sender: TObject);
private
public
Item : TTabItem;
end;
[...]
implementation
[...]
type
TCustomItem_subclass = class (TTabItem)
public
constructor Create(AOwner : TComponent); override;
end;
TCustomItem_sub_subclass = class (TCustomItem_subclass)
public
constructor Create(AOwner : TComponent); override;
function GetParentClassStyleLookupName: string; override;
end;
procedure TForm1.FormCreate(Sender: TObject);
procedure add_tab (t: TTabItem);
begin
t.Text := t.ClassName;
t.Parent := TabControl1
end;
begin
{$define UseSubSub}
{$ifdef UseSubSub}
Item := TCustomItem_sub_subclass.Create(TabControl1);
{$else}
Item := TCustomItem_subclass.Create(TabControl1);
{$endif}
Item.Text := Item.ClassName;
Item.Parent := TabControl1;
Caption := TabControl1.ActiveTab.Text;
Item := TCustomItem_subclass.Create(TabControl1);
Item.Text := Item.ClassName;
Item.Parent := TabControl1;
end;
constructor TCustomItem_subclass.Create(AOwner: TComponent);
begin
inherited;
end;
constructor TCustomItem_sub_subclass.Create(AOwner: TComponent);
begin
inherited;
end;
function TCustomItem_sub_subclass.GetParentClassStyleLookupName: string;
begin
Result := 'tabitemstyle';
end;
顺便说一句,在执行此操作时,我注意到该函数中似乎存在一个潜在的错误
FMX.Controls.Pas中的TStyledControl.GenerateStyleName(const AClassName: string): string
如果从前导AClassName
中删除的TCustom
参数以双TT开头,
与TCustomTabItem
中一样,该代码错误地删除了TabItem的T。我没有
时间或精力去进一步探索,但这就是为什么我的TabItem子类忽略的原因
Tab
的名字。