[英]How to change delphi firemonkey Speed button Lookup style at run time
[英]Firemonkey: cascade a styled Lookup change for a FMXObject where other objects inherit the stylename
我不確定是否可能-但似乎應該對我來說。 本質上,當我更改StyleLookup時,我想觸發所有組件以刷新其樣式。
我有一個FMXComponent,它是一個稱為BaseStyleLabel
的TLabel。 組件的StyleName
屬性為'BaseStyle' 。 它本身從樣式資源中查找其樣式,因此其StyleLookup
屬性設置為'BaseStyle1' 。 我也有'BaseStyle2' , 'BaseStyle3' ...
我有一個相關的TLabel被稱為MyTextLabel
及其StyleLookup
屬性設置為BaseStyle
,即的styleName BaseStyleLabel
。
一切似乎都正常。 我看到MyTextLabel
繼承的風格MyBaseStyle
“BaseStyle1”的。
當我執行這行代碼時
BaseStyleLabel.StyleLookup := 'BaseStyle2';
Self.repaint; // repaint whole form
我希望BaseStyleLabel
更改為“ BaseStyle2” (確實如此)。 但是, MyTextLabel
也應該更改樣式,然后看起來像是'BaseStyle2' ,但事實並非如此:它仍然是BaseStyle1
;
限定詞是BaseLabel和MyTextLabel都來自樣式資源。 它們實際上不是在表單上創建的組件,而是由樣式創建的。
所以我的問題是這個。
...編輯...。以下是請求的示例...
unit Unit1;
interface
uses
System.SysUtils, System.Types, System.UITypes, System.Classes, System.Variants,
FMX.Types, FMX.Graphics, FMX.Controls, FMX.Forms, FMX.Dialogs, FMX.StdCtrls;
type
TForm1 = class(TForm)
MyTextLabel: TLabel;
StyleBook1: TStyleBook;
BaseStyleLabel: TLabel;
Button1: TButton;
procedure Button1Click(Sender: TObject);
procedure FormCreate(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.fmx}
procedure TForm1.FormCreate(Sender: TObject);
begin
// Set up BaseStyleLabel as a Style Source
BaseStyleLabel.StyleName := 'BaseStyle';
// Set its Style to a Resources Style "STYLE ONE"
BaseStyleLabel.StyleLookup := 'BaseStyle1';
// Point MyTextLabel to whatever "BaseStyleLabel" is styled as...
MyTextLabel.StyleLookup := 'BaseStyle'; // also says "STYLE ONE"
end;
procedure TForm1.Button1Click(Sender: TObject);
begin
//Change BaseStyle Label to "STYLE TWO" (works OK)
BaseStyleLabel.StyleLookup := 'BaseStyle2';
// ... BUT MyTextLabel stays as "STYLE ONE"
// can I repaint???
// Auto Cascade?
// What about when Other TLabels are part of a different component style?
end;
end.
使用以下樣式文件
object TStyleContainer
object TLabel
StyleName = 'BaseStyle1'
DesignVisible = False
Height = 17.000000000000000000
Position.X = 521.000000000000000000
Position.Y = 432.000000000000000000
Text = 'STYLE ONE'
Width = 120.000000000000000000
end
object TLabel
StyleName = 'BaseStyle2'
DesignVisible = False
Height = 17.000000000000000000
Position.X = 521.000000000000000000
Position.Y = 432.000000000000000000
Text = 'STYLE TWO'
Width = 120.000000000000000000
end
object TLabel
StyleName = 'BaseStyle3'
Height = 17.000000000000000000
Position.X = 521.000000000000000000
Position.Y = 432.000000000000000000
Text = 'STYLE 3'
Width = 120.000000000000000000
end
end
好的-我一直在努力,可以提出解決方案。
我瀏覽了TStyledControl
的祖先類。 沒有全局觸發器可導致樣式查找級聯。 單個組件刷新其樣式的事實不會導致任何組件(恰好取決於該組件的StyleName)刷新。 因此,您似乎必須手動找到所有受影響的組件並進行更新。
這對我來說還不夠好,所以我為TStyledControl寫了一個輔助方法。
unit FMX.CascadingStyleLookup;
// Written by Glen Kleidon - 2018 - twitter: @sobaldrick4
interface
uses System.SysUtils, FMX.Types, FMX.Forms, FMX.Controls;
Type
TCascadingStyleLookup = Class Helper for TStyledControl
Procedure CascadeStyleLookup(AStyleLookup: String); overload;
procedure CascadeStyleLookup(AStyleLookup: string;
AComponent: TFMXObject); overload;
Function FindUltimateParentForm(AChild: TFMXObject): TFMXObject;
End;
implementation
procedure TCascadingStyleLookup.CascadeStyleLookup(AStyleLookup: String);
var
lUltimateParent: TFMXObject;
begin
// Apply New style to myself.
Self.styleLookup := AStyleLookup;
// Check if I have dependent Styles.
if (length(Self.StyleName) = 0) then
exit;
// Re-Apply my own style to everything.
lUltimateParent := Self.FindUltimateParentForm(Self);
if lUltimateParent <> nil then
CascadeStyleLookup(Self.StyleName, lUltimateParent);
end;
procedure TCascadingStyleLookup.CascadeStyleLookup(AStyleLookup: string;
AComponent: TFMXObject);
var
lChild: TFMXObject;
lStyledControl: TStyledControl;
begin
if (AComponent = nil) or (AComponent.Children = nil) then
exit;
if (AComponent.InheritsFrom(TStyledControl)) then
begin
lStyledControl := AComponent as TStyledControl;
if SameText(AStyleLookup, lStyledControl.styleLookup) then
begin
// re-apply
lStyledControl.styleLookup := AStyleLookup;
// Re-cascade this style.
if (length(lStyledControl.StyleName) > 0) and
(NOT(SameText(lStyledControl.styleLookup, AStyleLookup))) then
CascadeStyleLookup(lStyledControl.StyleName);
end;
end;
if AComponent.Children = nil then
exit;
// Check the children of this component for the style.
for lChild in AComponent.Children do
CascadeStyleLookup(AStyleLookup, lChild);
end;
function TCascadingStyleLookup.FindUltimateParentForm(AChild: TFMXObject)
: TFMXObject;
begin
Result := nil;
if (AChild.Parent <> nil) and (NOT(AChild.Parent.InheritsFrom(TForm))) then
Result := FindUltimateParentForm(AChild)
else
Result := AChild.Parent;
end;
end.
這允許自動搜索任何嵌套的“ stylelookup”屬性,並為該組件所駐留的整個表單進行更新。
我更新了附加組件我原來的例子MyTextLabel2
取決於風格MyTextLabel
。
因此,現在將BaseStyleLabel
設置為* BaseStyle1、2 或 3 *中的任何一個都將級聯到MyTextLabel。 當MyTextLabel更改其樣式時,它將級聯為MyTextLabel2。 因此,通過簡單地調用BaseStyleLabel.CascadeStyleLookup('BaseStyle2')
來更新BaseStyleLabel時,所有三個標簽都將顯示“ STYLE TWO”。
unit Unit1;
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.CascadingStyleLookup
;
type
TForm1 = class(TForm)
MyTextLabel: TLabel;
StyleBook1: TStyleBook;
BaseStyleLabel: TLabel;
Button1: TButton;
MyTextLabel2: TLabel;
procedure Button1Click(Sender: TObject);
procedure FormCreate(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.fmx}
procedure TForm1.FormCreate(Sender: TObject);
begin
// Set up BaseStyleLabel as a Style Source
BaseStyleLabel.StyleName := 'BaseStyle';
// Set its Style to a Resources Style "STYLE ONE"
BaseStyleLabel.StyleLookup := 'BaseStyle1';
// Point MyTextLabel to whatever "BaseStyleLabel" is styled as...
MyTextLabel.StyleName := 'MyTextBaseStyle';
MyTextLabel.StyleLookup := 'BaseStyle'; // also says "STYLE ONE"
// New component MyTextLabel2 points to whatever "MyTextLabel" is styled as...
MyTextLabel2.StyleLookup := 'MyTextBaseStyle'; // also says "STYLE ONE",
// (from MyTextLabel)
end;
procedure TForm1.Button1Click(Sender: TObject);
begin
// Change BaseStyle Label to "STYLE TWO" (now cascades to all)
BaseStyleLabel.CascadeStyleLookup('BaseStyle2');
end;
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.