Recent

Author Topic: Programmatically add expanded columns in a TStringGrid  (Read 1259 times)

Al3

  • New Member
  • *
  • Posts: 28
Programmatically add expanded columns in a TStringGrid
« on: January 29, 2025, 10:43:26 pm »
I just upgraded from Lazarus 3.4 to 3.8 with the hope that an issue I have will magically disappear, but here I am!
I am working in a separate unit where a class is defined.
The constructor of this class takes a TPageControl as a parameter and caches it.
When a method is called, it enters a parsing pipeline, does some blablabla, and then creates a TStringGrid and places it in the current (or new) TPageControl tab - TTabSheet.
Code: Pascal  [Select][+][-]
  1. Tab := instance.FPages.Pages[0]; // Uses the default tab
Then it creates a TStringGrid and places it inside:
Code: Pascal  [Select][+][-]
  1. Grid := TStringGrid.Create(Tab);
  2. Grid.Parent := Tab;
  3. Grid.Align := alClient;
  4. Grid.ScrollBars := ssBoth;
Finally, it adds custom columns in a loop based on a TStringList containing column names:
Code: Pascal  [Select][+][-]
  1. for columnName in columnNames do
  2. begin
  3.     Col := Grid.Columns.Add;
  4.     Col.Title.Caption := columnName;
  5.     Col.Alignment := taCenter; // nope
  6.     //Col.Expanded := true; // nope
  7. end;

So first of all, it does not seem to obey the column's Expanded and Alignment properties (The Alignment works only on editable cells, but not the columns).
And then I really want to fill up the entire available space with the columns, but setting the grid property "AutoFillColumns" to true breaks it completely -
It does not fit all the columns on the window, giving them way too much redundant space and the scrollbar does not even appear, making me really confused as to what is really happening and what am I doing wrong.
ChatGPT did not know what it was talking about, TStringGrid refpages and tutorials do not cover adding columns (at least "expanded") at runtime, google searches were only making references to Delphi and 2-3 not-very-related forum topics, mutating the "SizePriority" and "Width" properties did not fix the problem, AutoSizeColumns and AdjustSize didn't help either.

So I am hoping that this post clarifies things up a little  :D

« Last Edit: January 29, 2025, 11:11:18 pm by Al3 »

wp

  • Hero Member
  • *****
  • Posts: 12926
Re: Programmatically add expanded columns in a TStringGrid
« Reply #1 on: January 29, 2025, 11:17:34 pm »
I am afraid the property "Expanded" led you on the wrong track. I searched the entire grids unit for the word "Expanded" and only found comments like "// to do"...

The wiki article on grids explains how you can expand the columns to fill the entire client width and how you still can have some control on column width.

Code: Pascal  [Select][+][-]
  1. type
  2.   TForm1 = class(TForm)
  3.     procedure FormCreate(Sender: TObject);
  4.   private
  5.     Grid: TStringGrid;
  6.   public
  7.   end;
  8.  
  9. ...
  10.  
  11. procedure TForm1.FormCreate(Sender: TObject);
  12. var
  13.   i: Integer;
  14. begin
  15.   Grid := TStringGrid.Create(self);
  16.   Grid.Parent := self;
  17.   Grid.Align := alClient;
  18.   Grid.RowCount := 20;
  19.  
  20.   for i := 0 to 5 do
  21.     with Grid.Columns.Add do
  22.       Title.Caption := 'Col ' + IntToStr(i);
  23.  
  24.   with Grid.Columns[0] do
  25.   begin
  26.     Width := 50;
  27.     SizePriority := 0;
  28.   end;
  29.   with Grid.Columns[1] do
  30.   begin
  31.     Width := 100;
  32.     SizePriority := 0;
  33.   end;
  34.   with Grid.Columns[2] do
  35.   begin
  36.     Width := 100;
  37.     SizePriority := 0;
  38.   end;
  39.  
  40.   Grid.AutoFillColumns := true;
  41. end;                              

In this code, columns 0, 1, and 2 have a fixed width of 50, 100, 200 pixels while the remainder of the grid's client width is distributed evenly among the other columns, depending on the overall grid width.

Al3

  • New Member
  • *
  • Posts: 28
Re: Programmatically add expanded columns in a TStringGrid
« Reply #2 on: January 29, 2025, 11:36:52 pm »
I am afraid the property "Expanded" led you on the wrong track. I searched the entire grids unit for the word "Expanded" and only found comments like "// to do"...

The wiki article on grids explains how you can expand the columns to fill the entire client width and how you still can have some control on column width.

Code: Pascal  [Select][+][-]
  1. type
  2.   TForm1 = class(TForm)
  3.     procedure FormCreate(Sender: TObject);
  4.   private
  5.     Grid: TStringGrid;
  6.   public
  7.   end;
  8.  
  9. ...
  10.  
  11. procedure TForm1.FormCreate(Sender: TObject);
  12. var
  13.   i: Integer;
  14. begin
  15.   Grid := TStringGrid.Create(self);
  16.   Grid.Parent := self;
  17.   Grid.Align := alClient;
  18.   Grid.RowCount := 20;
  19.  
  20.   for i := 0 to 5 do
  21.     with Grid.Columns.Add do
  22.       Title.Caption := 'Col ' + IntToStr(i);
  23.  
  24.   with Grid.Columns[0] do
  25.   begin
  26.     Width := 50;
  27.     SizePriority := 0;
  28.   end;
  29.   with Grid.Columns[1] do
  30.   begin
  31.     Width := 100;
  32.     SizePriority := 0;
  33.   end;
  34.   with Grid.Columns[2] do
  35.   begin
  36.     Width := 100;
  37.     SizePriority := 0;
  38.   end;
  39.  
  40.   Grid.AutoFillColumns := true;
  41. end;                              

In this code, columns 0, 1, and 2 have a fixed width of 50, 100, 200 pixels while the remainder of the grid's client width is distributed evenly among the other columns, depending on the overall grid width.

Yes, but for me "Grid.AutoFillColumns := true" does not work as intended, as shown in the Screenshot.

wp

  • Hero Member
  • *****
  • Posts: 12926
Re: Programmatically add expanded columns in a TStringGrid
« Reply #3 on: January 30, 2025, 12:39:16 am »
To me it does... Did you run my code? What's your OS/widgetset? Normally, I am on Windows 11, using Laz 3.8 + FPC 3.2.2 (64 bit) or Laz/main + FPC 3.2.2 (32bit), but I also tested on Manjaro Linux with gtk2, gtk3, qt5 and qt6 widgetsets - no problem.

Al3

  • New Member
  • *
  • Posts: 28
Re: Programmatically add expanded columns in a TStringGrid
« Reply #4 on: January 30, 2025, 12:44:40 am »
To me it does... Did you run my code? What's your OS/widgetset? Normally, I am on Windows 11, using Laz 3.8 + FPC 3.2.2 (64 bit) or Laz/main + FPC 3.2.2 (32bit), but I also tested on Manjaro Linux with gtk2, gtk3, qt5 and qt6 widgetsets - no problem.
Current LCL widgetset: "win32"

I did not run your code, I'll do that now.
I did not run it, because mine is just as simple in its isolated form.
The difference is that I get it executed on a click event and the creator is not the TForm, but the tab.
It also defines columns with fixed size, but I am more so aiming at just every column having its size determined automatically, and distributed evenly across the available space (which should be the entire container).

Edit:
Coded like that, it does seem to work.
My version tries to do the same, just not from the main unit where the TForm is.
« Last Edit: January 30, 2025, 01:04:25 am by Al3 »

TRon

  • Hero Member
  • *****
  • Posts: 4377
Re: Programmatically add expanded columns in a TStringGrid
« Reply #5 on: January 30, 2025, 01:32:18 am »
Coded like that, it does seem to work.
My version tries to do the same, just not from the main unit where the TForm is.
A small hint you can apply: when you place a component on the form (whether it is on another component or not) then who is the owner of that component ? That (same) owner is to be passed to the creation of the component when created at runtime.
Today is tomorrow's yesterday.

Al3

  • New Member
  • *
  • Posts: 28
Re: Programmatically add expanded columns in a TStringGrid
« Reply #6 on: January 30, 2025, 02:11:31 am »
I even ran this code in my unit2's class' constructor (called in onclick event of the page tab in my unit1):
Code: Pascal  [Select][+][-]
  1. Tab := FPages.Pages[0];
  2. Grid := TStringGrid.Create(Tab);
  3. Grid.Parent := Tab;
  4. Grid.Align := alClient;
  5. Grid.RowCount := 2;
  6. for i := 0 to 11 do
  7.     with Grid.Columns.Add do
  8.     begin
  9.         Title.Caption := 'Col ' + IntToStr(i);
  10.     end;
  11. Grid.AutoFillColumns := true;

And the issue still remains, inclining me to believe that it might be related to the fact I am running this code from another unit..
Another possible explanation: using FPages.Pages[0] for the parent/owner, even though I have no idea why that would be a problem.

Edit: The issue is not the unit.
The code did not work even in the main unit, but it did work when I used self instead of FPages.Pages[0] in there.
It is a very weird behavior to happen because of such a thing nonetheless and I am still in the process of figuring out what's the problem with using FPages.Pages[0].
« Last Edit: January 30, 2025, 02:17:55 am by Al3 »

Al3

  • New Member
  • *
  • Posts: 28
Re: Programmatically add expanded columns in a TStringGrid
« Reply #7 on: January 30, 2025, 02:29:47 am »
After a lot of tests, it seems like the issue arises, because the parent is set to be the TTabSheet in the page control.
It does work in the main unit if the parent is the form instance.

I am very inclined to believe that this is a bug in the component.
Not only, because of this issue, but also because when the "AutoSize" property is set, setting the grid width does not affect the TTabSheet even though it should.
As a result, the grid gets cut off as if it was successfully resized, but not the parent, akin to the issue that I have.
« Last Edit: January 30, 2025, 03:13:31 am by Al3 »

wp

  • Hero Member
  • *****
  • Posts: 12926
Re: Programmatically add expanded columns in a TStringGrid
« Reply #8 on: January 30, 2025, 10:53:16 am »
I am attaching a new version of my code. Now we have a TPageControl and a button. With every click on the button a new tab is added to the pagecontrol, a grid is created (like before), but inserted into the tab having the tab as both owner and parent. - No problem.

Probably there are numerous ways to add a new tab to a page control. Please show what you are doing, ideally create a small simplified, but compilable project and post it here. Your description that the grid was cut off might indicate that you insert the grid too early when the new tab is not yet ready for accepting components.

Al3

  • New Member
  • *
  • Posts: 28
Re: Programmatically add expanded columns in a TStringGrid
« Reply #9 on: January 30, 2025, 12:39:26 pm »
I am attaching a new version of my code. Now we have a TPageControl and a button. With every click on the button a new tab is added to the pagecontrol, a grid is created (like before), but inserted into the tab having the tab as both owner and parent. - No problem.

Probably there are numerous ways to add a new tab to a page control. Please show what you are doing, ideally create a small simplified, but compilable project and post it here. Your description that the grid was cut off might indicate that you insert the grid too early when the new tab is not yet ready for accepting components.
The last time I tested, it was on a tab that was already created by the UI designer, not programmatically.
It was just on the page's button click event the minimal code that you illustrated, but with the parent set to the tab.

Right now the tab is glitched and stuck being half-sized after I unchecked the "AutoSize" property.
Last time this happened, it magically changed back to its normal size.

I tried different things to unglitch it, such as unchecking and checking the "Visible" option. Now it is stuck in its invisible state.

Note that my page control (which uses bottom tab layout) is actually placed in a tab of another page control, which is what *might* be causing these issues.
Still, working cleanly in the project that you provided, the issue has not yet surfaced.
« Last Edit: January 30, 2025, 01:17:22 pm by Al3 »

Al3

  • New Member
  • *
  • Posts: 28
Re: Programmatically add expanded columns in a TStringGrid
« Reply #10 on: January 30, 2025, 03:50:11 pm »
Yes, it was a bugged.
I deleted and re-created the page control and this fixed the issue.

 

TinyPortal © 2005-2018