Recent

Author Topic: I Hate Grids -  (Read 8515 times)

JLWest

  • Hero Member
  • *****
  • Posts: 1293
I Hate Grids -
« on: April 13, 2018, 05:59:42 am »
I'm unable to set the Column Alignments, Justify Right, Center and Left.

Get a bounds error;

So I wrote a small test program. (Attached)

I'm getting the error on the following lines:

     obj.Columns[1].Alignment := taRightJustify;
     obj.Columns[1].Title.Alignment := taCenter; 

The test program is 1 form and unit. uncoment the lines and it throws an error.

Could someone take a look and tell me where I'm going wrong.

Thanks

 
FPC 3.2.0, Lazarus IDE v2.0.4
 Windows 10 Pro 32-GB
 Intel i7 770K CPU 4.2GHz 32702MB Ram
GeForce GTX 1080 Graphics - 8 Gig
4.1 TB

Handoko

  • Hero Member
  • *****
  • Posts: 5131
  • My goal: build my own game engine using Lazarus
Re: I Hate Grids -
« Reply #1 on: April 13, 2018, 06:23:36 am »
As mentioned by @taazz previously, you cannot combine Columns and ColCount/RowCount.

I can think 3 solutions for your case:
1. Use only Columns (+ OnDrawCell if you want to set alignment for FixedColumn)
2. Don't use Columns but you may use OnPrepareCell to manually set the cells' alignment
3. Don't use StringGrid

For solution #2, I remember there is an example in the wiki (or maybe forum) that shows us how to do it.

For solution #3, maybe you can use DrawGrid, which offer more flexibility but harder to use. Or use any third party components. One awesome grid that can be used in Lazarus is TMS Grid Pack:
https://www.tmssoftware.com/site/gridpack.asp

Quote
I Hate Grids
Actually, it is fun playing with grids. I can make it colorful and has multiple column search ability:
http://forum.lazarus.freepascal.org/index.php/topic,37181.msg249361.html#msg249361
« Last Edit: April 13, 2018, 06:37:13 am by Handoko »

JLWest

  • Hero Member
  • *****
  • Posts: 1293
Re: I Hate Grids -
« Reply #2 on: April 13, 2018, 07:00:51 am »
I can't use columns with ColCount/RowCount.

I'm not entirely sure what you mean.

dose that mean I can't use:

 TString1.Columns[1].Alignment := taRightJustify;

because that's where the error is thrown.

Is there another command I can use to set the alignment or other commands besides ColCount/RowCount that I can use that will work with TString1.Columns[1].Alignment := taRightJustify;.

Or is what I want to do not possible.
FPC 3.2.0, Lazarus IDE v2.0.4
 Windows 10 Pro 32-GB
 Intel i7 770K CPU 4.2GHz 32702MB Ram
GeForce GTX 1080 Graphics - 8 Gig
4.1 TB

Handoko

  • Hero Member
  • *****
  • Posts: 5131
  • My goal: build my own game engine using Lazarus
Re: I Hate Grids -
« Reply #3 on: April 13, 2018, 07:46:36 am »
You will get errors when accessing columns property if you ever access Colcount/RowCount previously.


I already provided you the example code for solution #1 some days ago. If you have problem with it, you can ask or post the code here, others will inspect the code and explain it for you.


Is there another command I can use to set the alignment or other commands besides ColCount/RowCount that I can use that will work with TString1.Columns[1].Alignment := taRightJustify;.


As far as I know, no. Only workarounds are available (solution #1 and #2). If you have problem understanding my solution #1, you may have problem to understand solution #2 too.


I'm not on my computer now. You can search the forum or wiki for changing the title alignment.
« Last Edit: April 13, 2018, 08:17:57 am by Handoko »

wp

  • Hero Member
  • *****
  • Posts: 11858
Re: I Hate Grids -
« Reply #4 on: April 13, 2018, 09:59:17 am »
Of course, if you want to use the grid's Columns you must add all Columns required by clicking '...' next to property Columns. Columns are not created when you set ColCount!

Did you read the excellent wiki documentation of the Lazarus grids? http://wiki.lazarus.freepascal.org/Grids_Reference_Page#property_Columns

JLWest

  • Hero Member
  • *****
  • Posts: 1293
Re: I Hate Grids -
« Reply #5 on: April 13, 2018, 10:23:09 am »
Ok I'll re-examine that code example:

If I remember I tried to use the code and had a lot of problems adapting the code to my requirements.

The records are in a listbox.
 
There are about 35 different record formats and over 2,500 records. Lots of duplicate record types. Lots of different record formats.

You double click on a record in the listbox.
From the first field in the listbox you can determine the record type.

From there you would setup a grid required to display the parsed record.

Some records require a grid with 2 columns, some 3, some 4 and others 5 columns.

The required configuration of the grid is always changing.

You may go from a two column grid with data right justified for one record and then select another record that requires 5 columns with everything left justified.

I need to call a a procedure that would set the following:

Number of Fixed Rows                  Always 1
Number of Fixed Columns              Always 1
Number of Free Columns               2 to 5 depending on Record Type.
Number of Free Rows                    Could be in the 100's but Taazz showed a way to just keep adding  rows
Justification for each Columns         Left, Right, Centered

So I can't do that in one procedure because Columns and ColCount/RowCount will not work together if I understand this right.

Is it they can't be used in the same function/procedure or unit  or project.

Could I have 4 procedure:

Procedure SetColRow(aCol : integer; aRow : Integer);     // Set Free Col and Rows
procedure SetWidths (aVector : Array);                          // Array of Integers with Col/Width
procedure SetAlighments (aVector : Array);                    // Array of Integers with Col/Alignment
Procedure SetHeadings (AVector : Array);                      // Array of Strings with Col/Headings


 
FPC 3.2.0, Lazarus IDE v2.0.4
 Windows 10 Pro 32-GB
 Intel i7 770K CPU 4.2GHz 32702MB Ram
GeForce GTX 1080 Graphics - 8 Gig
4.1 TB

JLWest

  • Hero Member
  • *****
  • Posts: 1293
Re: I Hate Grids -
« Reply #6 on: April 13, 2018, 10:33:05 am »
Of course, if you want to use the grid's Columns you must add all Columns required by clicking '...' next to property Columns. Columns are not created when you set ColCount!

Did you read the excellent wiki documentation of the Lazarus grids? http://wiki.lazarus.freepascal.org/Grids_Reference_Page#property_Columns

Yes, I have read it several times and keep going back to it. All the examples assume you set up a grid and that's it.

It's 2 in the morning and I have to quit for the day.

I need the ability to constantly change the grid during the running of the program.

I think you are being very generous call it excellent documentation.

It may well be that for someone who knows Free Pascal, but for me not so much.
« Last Edit: April 13, 2018, 10:34:45 am by JLWest »
FPC 3.2.0, Lazarus IDE v2.0.4
 Windows 10 Pro 32-GB
 Intel i7 770K CPU 4.2GHz 32702MB Ram
GeForce GTX 1080 Graphics - 8 Gig
4.1 TB

wp

  • Hero Member
  • *****
  • Posts: 11858
Re: I Hate Grids -
« Reply #7 on: April 13, 2018, 10:41:34 am »
Try this simple procedure, it sets as many columns with dedicated attributes as you want.
Code: Pascal  [Select][+][-]
  1. procedure SetupGrid(AGrid: TStringGrid; ARowCount: Integer; AHeaders: array of string;
  2.   AColWidths: Array of Integer; AAlignments: Array of TAlignment);
  3. var
  4.   i: Integer;
  5.   n: Integer;
  6. begin
  7.   n := Length(AHeaders);
  8.   if (n <> Length(AColWidths)) and (n <> Length(AAlignments)) then
  9.     Raise Exception.Create('Equal array dimensions required');
  10.  
  11.   AGrid.BeginUpdate;
  12.   try
  13.     AGrid.RowCount := ARowCount + AGrid.FixedRows;
  14.     AGrid.Columns.Clear;
  15.     for i:=0 to n-1 do
  16.       with AGrid.Columns.Add do begin
  17.         Title.Caption := AHeaders[i];
  18.         Title.Alignment := AAlignments[i];
  19.         Title.Font.Style := [fsBold];
  20.         Width := AColWidths[i];
  21.         Alignment := AAlignments[i];
  22.       end;
  23.   finally
  24.     AGrid.EndUpdate;
  25.   end;
  26. end;
  27.  
  28. procedure TForm1.Button1Click(Sender: TObject);
  29. begin
  30.   SetupGrid(StringGrid1, 3, ['Col1', 'Col2', 'Col3'], [100, 50, 75], [taLeftJustify, taCenter, taRightJustify]);
  31. end;
  32.  
  33. procedure TForm1.Button2Click(Sender: TObject);
  34. begin
  35.   SetupGrid(StringGrid1, 10, ['C1', 'C2', 'C3', 'C4'], [80, 80, 80, 40], [taCenter, taCenter, taCenter, taRightJustify]);
  36. end;
« Last Edit: April 13, 2018, 10:51:43 am by wp »

Handoko

  • Hero Member
  • *****
  • Posts: 5131
  • My goal: build my own game engine using Lazarus
Re: I Hate Grids -
« Reply #8 on: April 13, 2018, 11:10:59 am »
@wp

Yes, your code works. But if I remember correctly, the TS also want to customize the width and alignment of the fixed column.

I provided him my example code that solves all his requirements but he cannot fully understand it and he said he got error when try to use it in his project.

This is my code (solution #1 - using OnDrawCell):

Code: Pascal  [Select][+][-]
  1. unit Unit1;
  2.  
  3. {$mode objfpc}{$H+}
  4.  
  5. interface
  6.  
  7. uses
  8.   Classes, Forms, Controls, Graphics, Grids, Types;
  9.  
  10. type
  11.  
  12.   { TForm1 }
  13.  
  14.   TForm1 = class(TForm)
  15.     StringGrid1: TStringGrid;
  16.     procedure FormCreate(Sender: TObject);
  17.     procedure StringGrid1DrawCell(Sender: TObject; aCol, aRow: Integer;
  18.       aRect: TRect; aState: TGridDrawState);
  19.   end;
  20.  
  21. var
  22.   Form1: TForm1;
  23.  
  24. implementation
  25.  
  26. {$R *.lfm}
  27.  
  28. { TForm1 }
  29.  
  30. procedure TForm1.FormCreate(Sender: TObject);
  31. begin
  32.   with StringGrid1 do begin
  33.  
  34.     DefaultColWidth := 100; // to customize fixed column's width
  35.     Clear;
  36.  
  37.     // Add 4 columns
  38.     Columns.Add;
  39.     Columns.Add;
  40.     Columns.Add;
  41.     Columns.Add;
  42.  
  43.     // Set the width
  44.     Columns[0].Width := 100;
  45.     Columns[1].Width := 50;
  46.     Columns[2].Width := 100;
  47.     Columns[3].Width := 100;
  48.  
  49.     // Set the alignments
  50.     Columns[0].Alignment := taRightJustify;
  51.     Columns[1].Alignment := taRightJustify;
  52.     Columns[2].Alignment := taCenter;
  53.     Columns[3].Alignment := taLeftJustify;
  54.  
  55.     // Set the header's alignments
  56.     Columns[0].Title.Alignment := taCenter;
  57.     Columns[1].Title.Alignment := taCenter;
  58.     Columns[2].Title.Alignment := taCenter;
  59.     Columns[3].Title.Alignment := taCenter;
  60.  
  61.     // Set the header's texts
  62.     Columns[0].Title.Caption := 'A';
  63.     Columns[1].Title.Caption := 'B';
  64.     Columns[2].Title.Caption := 'C';
  65.     Columns[3].Title.Caption := 'D';
  66.  
  67.     // Put some data
  68.     Cells[0, 1] := 'one';   Cells[1, 1] := '123';  Cells[2, 1] := '1'; Cells[3, 1] := 'tokyo';   Cells[4, 1] := 'leopard';
  69.     Cells[0, 2] := 'two';   Cells[1, 2] := '80';   Cells[2, 2] := '2'; Cells[3, 2] := 'mexico';  Cells[4, 2] := 'dog';
  70.     Cells[0, 3] := 'three'; Cells[1, 3] := '2048'; Cells[2, 3] := '3'; Cells[3, 3] := 'paris';   Cells[4, 3] := 'cat';
  71.     Cells[0, 4] := 'four';  Cells[1, 4] := '7';    Cells[2, 4] := '4'; Cells[3, 4] := 'beijing'; Cells[4, 4] := 'fish';
  72.  
  73.   end;
  74. end;
  75.  
  76. procedure TForm1.StringGrid1DrawCell(Sender: TObject; aCol, aRow: Integer;
  77.   aRect: TRect; aState: TGridDrawState);
  78. var
  79.   TextStyle : TTextStyle;
  80.   Pos       : TRect;
  81. begin
  82.  
  83.   if aCol <> 0 then Exit;
  84.  
  85.   StringGrid1.Canvas.Brush.Color := cl3DFace;
  86.   StringGrid1.Canvas.FillRect(aRect);
  87.   StringGrid1.Canvas.Pen.Color := clInfoText;
  88.  
  89.   TextStyle.Alignment   := taRightJustify;
  90.   TextStyle.Layout      := tlBottom;
  91.   TextStyle.SingleLine  := True;
  92.   TextStyle.Clipping    := True;
  93.   TextStyle.ExpandTabs  := True;
  94.   TextStyle.ShowPrefix  := True;
  95.   TextStyle.Wordbreak   := True;
  96.   TextStyle.Opaque      := False;
  97.   TextStyle.SystemFont  := False;
  98.   TextStyle.RightToLeft := False;
  99.   TextStyle.EndEllipsis := False;
  100.  
  101.   Pos := aRect;
  102.   Dec(Pos.Bottom, 4);
  103.   Dec(Pos.Right,  5);
  104.   StringGrid1.Canvas.TextRect(Pos, 0, 10, StringGrid1.Cells[aCol, aRow], TextStyle);
  105.  
  106. end;
  107.  
  108. end.

For solution #2 - using OnPrepareCanvas can be found here:
https://forum.lazarus.freepascal.org/index.php/topic,17572.msg97061.html#msg97061
« Last Edit: April 13, 2018, 11:15:53 am by Handoko »

wp

  • Hero Member
  • *****
  • Posts: 11858
Re: I Hate Grids -
« Reply #9 on: April 13, 2018, 12:22:24 pm »
I don't know what the TS does to make your code not work. To give him a hand I am adding a (modified) version of the my code above in a full (working) project.

The main routine is
Code: Text  [Select][+][-]
  1.   procedure SetupGrid(AGrid: TStringGrid; ARowCount: Integer;
  2.     AFixedColWidth: Integer; AFixedColAlignment: TAlignment;
  3.     AColHeaders: array of string; AColWidths: Array of Integer;
  4.     AColAlignments: Array of TAlignment);
which gets these parameters:
  • AGrid: grid to be processed
  • ARowCount: Number of data rows the grid should have (the total row count is higher by 1 because of the fixed row)
  • AFixedColWidth: Width of the fixed column, in pixels
  • AFixedColAlignment: Justification of the texts in the fixed column. The value is stored in an intermediate form variable and applied in the grids's OnPrepareCanvas whenever the grid is painted - look at the wiki docs of the grid to understand what OnPrepareCanvas is doing, I have written it so many times... This approach must be selected because the fixed column is not a TGridColumn like the data columns which provides a property for it.
  • AColHeaders: an open array with the titles of each data column. The number of the columns created will depend on the number of array elements.
  • AColWidths: open array with the widths of each data column. The length of the array must match the length of AColHeaders.
  • AColAlignments: open array with the alignments of each data column. The length of the array must match the length of AColHeaders.
Since I don't have "real" data I added the procedure "AddDummyData" which populates the grid with some nonsense data. Replace it with a procedure which provided your real data.

Click on any of the three buttons to activate a different layout.
« Last Edit: April 15, 2018, 12:03:13 am by wp »

Edson

  • Hero Member
  • *****
  • Posts: 1301
Re: I Hate Grids -
« Reply #10 on: April 13, 2018, 05:18:05 pm »
Working with StringGrid, give me problems too. That's why I created my library https://github.com/t-edson/UtilsGrilla
Among ohter facilities, it can define many templates for a TStringGrid (colums, width, alignment, ...), and then reconfigure the grid using just one instruction.
Lazarus 2.2.6 - FPC 3.2.2 - x86_64-win64 on Windows 10

Handoko

  • Hero Member
  • *****
  • Posts: 5131
  • My goal: build my own game engine using Lazarus
Re: I Hate Grids -
« Reply #11 on: April 13, 2018, 05:33:32 pm »
Oh, that's great. Me too had problems working with grids. Please add it to the OPM and if you have time, please consider to add English description.

JLWest

  • Hero Member
  • *****
  • Posts: 1293
Re: I Hate Grids -
« Reply #12 on: April 13, 2018, 06:27:17 pm »
@Handoko

I got the OnDrawCell solution working.

 I parsed a RowCode 100 record with Four Columns, everything Left Justified and 46 rows then needed to change the grid to 2 columns to parse the RowCode 14 Record.

I could never figure out how to make the OnDrawCell solution do that without throwing errors.

I don't care that much about the Fixed Rows and Fixed Cols.

Well it's the 13, April. I have to take a few days off and do I my taxes. I'll get back to this next week sometime.

Thanks for all the help.

I need to reconfigure the grid multiple times during the execution of the program with
different column widths for each column, different alignments for each column, right, left and center. It would be nice to center my headings in the fixed row but I could live with whatever.
« Last Edit: April 13, 2018, 06:29:58 pm by JLWest »
FPC 3.2.0, Lazarus IDE v2.0.4
 Windows 10 Pro 32-GB
 Intel i7 770K CPU 4.2GHz 32702MB Ram
GeForce GTX 1080 Graphics - 8 Gig
4.1 TB

Handoko

  • Hero Member
  • *****
  • Posts: 5131
  • My goal: build my own game engine using Lazarus
Re: I Hate Grids -
« Reply #13 on: April 13, 2018, 06:37:08 pm »
You can try wp's code or Edson's UtilsGrilla, they should work without problem.

But if you want to learn, you can provide your code that showing errors after trying to use my solution (OnDrawCell). Send the zip file here, so we can tell you where you did wrong. Remove all the unnecessary parts, keep only the data file and the compilable source code that contains the errors.

JLWest

  • Hero Member
  • *****
  • Posts: 1293
Re: I Hate Grids -
« Reply #14 on: April 13, 2018, 08:02:02 pm »
" Handoko

After I get my Taxes Filed I'll set up a small program with a small data file with 4 or five different formats and post it.

Thanks

Oh, by the way Edson's UtilsGrilla, is in Spanish I think. Having a difficult time with English Free Pascal.

Can't take on Spanish also.
« Last Edit: April 13, 2018, 08:04:47 pm by JLWest »
FPC 3.2.0, Lazarus IDE v2.0.4
 Windows 10 Pro 32-GB
 Intel i7 770K CPU 4.2GHz 32702MB Ram
GeForce GTX 1080 Graphics - 8 Gig
4.1 TB

 

TinyPortal © 2005-2018