Results 1 to 5 of 5

Thread: Font instellingen doorgeven

  1. #1

    Font instellingen doorgeven

    hallo allemaal

    Ik heb een ObjectList van het type Ttextbox
    Deze TTextBox bevat een Font en een Position

    Via een editor kan je de Font van de geselecteerde Textbox aanpassen (in een combobox laat ik al mijn textboxes zien)
    Hierbij geef ik de huidige Font van de Textbox door aan een FontDialog.
    De gekozen font instellingen uit de FOntDialog geef ik daarna weer teug aan de geselecteerde TextBox. (zeg TextBox1)

    Tot zover gaat het goed

    Vervolgens selecteer ik een andere textbox uit de lijst (TextBox2) en wordt de bovenstaande riedel opnieuw uitgevoerd.
    De FontDialog laat nu dan ook keurig de Fontinstellingen zien van de font instellingen van TextBox2.
    Eventuele aanpassingen hierop worden ook weer netjes terug gegeven aan TextBox2.

    Nu selecteer ik daarna weer de TextBox1.
    Echter nu krijg ik de Settings van TextBox2 te zien.

    Daarbij krijg ik bij het afsluiten van het programma een AV omdat er een object niet opgeruimd kan worden.

    Kortom ik doe wat fout bij het aanmaken van de fonts en het doorgeven

    Wat zou de juiste manier hiervoor zijn.

  2. #2
    Ter verduidelijking even een simpel programmatje gemaakt met een combox een label en een FontDialog

    Code:
      TTextBoxSettings =  class(Tobject)
      private
        FFont: TFont;
        FPosition: TRect;
        FName: string;
    
      public
       Constructor create;
       Destructor Destroy; override;
    
      published
       property Font : TFont read FFont write FFont;
       property Position :TRect read FPosition write FPosition;
       Property Name:string read FName write FName;
    end;
    
    procedure TForm1.ComboBox1Change(Sender: TObject);
    begin
    label1.Caption:= TextBoxes[combobox1.ItemIndex].Font.Name; //huidige naam laten zien
    if FontDialog1.Execute() then
    begin
     TextBoxes[combobox1.ItemIndex].Font:=FontDialog1.Font;
     label1.Caption:= TextBoxes[combobox1.ItemIndex].Font.Name; // de nieuw gekozen naam laten zien.
    end;
    end;
    
    procedure TForm1.FormCreate(Sender: TObject);
    var tempTextbox:TTextboxSettings;
    i:integer;
    tempfont:Tfont;
    begin
    
    textboxes:= TObjectList<TTextboxSettings>.Create;
    tempTextbox:=TTextboxSettings.create;
    tempTextBox.Name:='Textbox1';
    tempfont:=Tfont.Create;
    tempfont.Name:='Arial';
    tempTextBox.Font:=tempFont;
    Textboxes.Add(tempTextBox);
    
    tempTextbox:=TTextboxSettings.create;
    tempTextBox.Name:='Textbox2';
    tempfont:=Tfont.Create;
    tempfont.Name:='Calibre';
    tempTextBox.Font:=tempFont;
    Textboxes.Add(tempTextBox);
    
    tempTextbox:=TTextboxSettings.create;
    tempTextBox.Name:='Textbox3';
    tempfont:=Tfont.Create;
    tempfont.Name:='Arial';
    tempTextBox.Font:=tempFont;
    Textboxes.Add(tempTextBox);
    
    combobox1.Clear;
    for i := 0 to TextBoxes.Count-1 do
    begin
     combobox1.Items.Add(TextBoxes[i].Name);
    
    end;
    end;
    
    { TTextBoxSettings }
    
    constructor TTextBoxSettings.create;
    begin
    //
    end;
    
    destructor TTextBoxSettings.Destroy;
    begin
    
      inherited;
    end;

  3. #3
    Fornicatorus Formicidae VideoRipper's Avatar
    Join Date
    Mar 2005
    Location
    Vicus Saltus Orientalem
    Posts
    5,708
    Ik weet niet of er bij het koppie-peesten iets mis ging, maar: Indenten?

    De basis is altijd: het leven van objecten zijn altijd (een heeeeele enkele uitzondering daargelaten) de verantwoordelijkheid van de eigenaar, nooit van de aanroepende code.

    In dit geval is TTextBoxSettings de eigenaar van het FFont object en moet deze ervoor zorgen dat hij wordt aangemaakt en opgeruimd.
    TForm1 is de eigenaar van TTextBoxSettings dus is hier verantwoordelijk voor en zolang je informatie nodig hebt van het object, moet deze beschikbaar blijven (ik neem aan dat je die dan ook weer vrijgeeft in de FormDestroy van de form, maar heb je die weggelaten in je code hierboven).
    Om een kopie te maken van een object gebruik ik (bij voorkeur, want alleen afgeleiden van TPersistent hebben het geimplementeerd) Assign en niet :=, dit om te voorkomen dat je een instance kunt overschrijven (en dus memory leaks krijgt); van sommige objecten (ik geloof TStrings) kun je ook veilig een kopie maken met := , maar met Assign() weet je het zeker.

    Delphi Code:
    1. unit Unit1;
    2.  
    3. interface
    4.  
    5. uses
    6.   Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
    7.   StdCtrls, Generics.Collections;
    8.  
    9. type
    10.   TTextBoxSettings = class(TObject)
    11.   private
    12.     FFont: TFont;
    13.     FPosition: TRect;
    14.     FName: string;
    15.   public
    16.    constructor Create(AName: string = ''; AFontName: string = '');
    17.    destructor Destroy; override;
    18.  
    19.    property Font: TFont read FFont;
    20.    property Position: TRect read FPosition;
    21.    Property Name: string read FName write FName;
    22.   end;
    23.  
    24.   TForm1 = class(TForm)
    25.     ComboBox1: TComboBox;
    26.     FontDialog1: TFontDialog;
    27.     Label1: TLabel;
    28.     procedure FormCreate(Sender: TObject);
    29.     procedure FormDestroy(Sender: TObject);
    30.     procedure ComboBox1Change(Sender: TObject);
    31.   private
    32.     FTextBoxes: TObjectList<TTextboxSettings>;
    33.     procedure RefreshCombo;
    34.     procedure UpdateLabel;
    35.   public
    36.     { Public declarations }
    37.   end;
    38.  
    39. var
    40.   Form1: TForm1;
    41.  
    42. implementation
    43.  
    44. {$R *.dfm}
    45.  
    46. { TTextBoxSettings }
    47.  
    48. constructor TTextBoxSettings.Create(AName: string = ''; AFontName: string = '');
    49. begin
    50.   inherited Create;
    51.  
    52.   FName := AName;
    53.   FFont := TFont.Create;
    54.   FFont.Name := AFontName;
    55. end;
    56.  
    57. destructor TTextBoxSettings.Destroy;
    58. begin
    59.   FFont.Free;
    60.  
    61.   inherited Destroy;
    62. end;
    63.  
    64. { TForm1 }
    65.  
    66. procedure TForm1.FormCreate(Sender: TObject);
    67. begin
    68.   FTextBoxes := TObjectList<TTextboxSettings>.Create;
    69.  
    70.   FTextboxes.Add(TTextboxSettings.Create('Textbox1', 'Arial'));
    71.   FTextboxes.Add(TTextboxSettings.Create('Textbox2', 'Calibre'));
    72.   FTextboxes.Add(TTextboxSettings.Create('Textbox3', 'Arial'));
    73.   RefreshCombo;
    74.   UpdateLabel;
    75. end;
    76.  
    77. procedure TForm1.FormDestroy(Sender: TObject);
    78. begin
    79.   FTextBoxes.Free;
    80. end;
    81.  
    82. procedure TForm1.ComboBox1Change(Sender: TObject);
    83. begin
    84.   if (ComboBox1.ItemIndex >= 0) and
    85.      (ComboBox1.ItemIndex < FTextBoxes.Count) then
    86.   begin
    87.     FontDialog1.Font.Assign(FTextBoxes[ComboBox1.ItemIndex].Font);
    88.     if FontDialog1.Execute(Handle) then
    89.       FTextBoxes[ComboBox1.ItemIndex].Font.Assign(FontDialog1.Font);
    90.   end;
    91.   UpdateLabel;
    92. end;
    93.  
    94. procedure TForm1.RefreshCombo;
    95. var
    96.   iIndex: Integer;
    97. begin
    98.   ComboBox1.Items.BeginUpdate;
    99.   try
    100.     ComboBox1.Items.Clear;
    101.     for iIndex := 0 to Pred(FTextBoxes.Count) do
    102.       ComboBox1.Items.Add(FTextBoxes[iIndex].Name);
    103.     ComboBox1.ItemIndex := 0;
    104.   finally
    105.     ComboBox1.Items.EndUpdate;
    106.   end;
    107. end;
    108.  
    109. procedure TForm1.UpdateLabel;
    110. begin
    111.   if (ComboBox1.ItemIndex >= 0) and
    112.      (ComboBox1.ItemIndex < FTextBoxes.Count) then
    113.     Label1.Caption := FTextBoxes[Combobox1.ItemIndex].Font.Name //huidige naam laten zien
    114.   else
    115.     Label1.Caption := '';
    116. end;
    117.  
    118. end.
    Last edited by VideoRipper; 29-Apr-22 at 14:36.
    TMemoryLeak.Create(Nil);

  4. #4
    Thanks voor de uitleg.
    Mijn code was idd even heel kort door de bocht dus weinig aandacht besteed aan de opmaak.
    De truuk zit hem dus in het gebruik van de Assign functie.

    In mijn test programma werkt het nu.

    Na wat kleine aanpassingen ook in mij originele programma.
    Ook het vrijgeven gaat nu goed (Geen Memoryleak en geen AV's)

  5. #5
    Bij veel VCL properties, wordt achter de schermen Assign aangeroepen als je toekent aan een property.

    Koe.Font := Big.Font, doet achter de schermen dus eigenlijk Koe.Font.Assign(Big.Font). Beide objecten houden hun eigen TFont-instantie, en alleen de eigenschappen van het font worden overgenomen. Maar als je dat als uitgangspunt neemt, en je treft een keer een property setter die dat niet doet, dan gaat het mogelijk mis, omdat er dan twee objecten een TFont-instantie delen.
    Dat gaat extra-super-fout als Koe iets met het font wil gaan doen, terwijl Big, als legitieme eigenaar, z'n instantie heeft opgeruimd.

    Het overigens wel getuigen van een zeer matige implementatie in Koe. Deze zou óf Assign moeten doen, óf een FreeNotification instellen op het font, zodat hij z'n verwijzing ernaar kan opruimen als Big het font vrijgeeft. En natuurlijk een beetje netjes de situatie afhandelen als hij een font nodig heeft, maar het niet heeft.
    Maar goed, expliciet Assign gebruiken is inderdaad vaak wel duidelijker.
    1+1=b

Thread Information

Users Browsing this Thread

There are currently 1 users browsing this thread. (0 members and 1 guests)

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •