簡體   English   中英

Firemonkey:級聯FMXObject的樣式化Lookup更改,其中其他對象繼承樣式名

[英]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都來自樣式資源。 它們實際上不是在表單上創建的組件,而是由樣式創建的。

所以我的問題是這個。

  1. 這種方法有效嗎?
  2. 是否有標准方法,例如使用可以更新的樣式對象?
  3. 我只是沒有刷新正確的事情嗎?
  4. 使用錯誤的方法刷新,也許ApplyStyle?

...編輯...。以下是請求的示例...

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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM