Lazarus IDE 中支持数字(浮点数或整数)的自定义网格组件

A custom grid component with number (float or integer) support in Lazarus IDE

在 Lazarus(和任何其他 RAD)中,TStringGrid 视觉组件是来自 DataSet 或 self-contained 的 input/output 数据的关键组件。此数据以字符串数据类型存储在单元格中。

我想知道是否有任何自定义网格组件支持浮点数或整数操作以及相关方法。

例如:
一个网格组件,它捕获用户在单元格中的输入(像往常一样),如果捕获的数据是 String,则在内部自动将此数据输入转换为相应的数值,如 SingleInteger 用于实际操作和显示数据的数据类型。

此外,如果修改了单元格的数值,则也更改字符串表示形式。

我认为这样的组件在我们需要一个仅存储数值的网格(可能不包含 header 行)的情况下非常有用。

你们中的任何人都可以知道是否存在这样的组件或提供有关此组件的示例或源代码吗?

非常感谢和最诚挚的问候

答案取决于你用 "float or integer number manipulation" 表达的意思。

如果你想在网格中执行计算,就像在电子表格中一样,你应该试试 fpspreadsheet 包(https://sourceforge.net/projects/lazarus-ccr/files/FPSpreadsheet/fpspreadsheet-1.6.2.zip/download, or https://sourceforge.net/p/lazarus-ccr/svn/HEAD/tree/components/fpspreadsheet/). It contains a dedicated grid in which you can enter formulas like in Excel. Each cell stores data essentially as string or number,depending on the data type. See http://wiki.lazarus.freepascal.org/TsWorksheetGrid 以获得介绍。

另一方面,如果您有 "matrix" 个数字(二维数组)并且想要 在网格中显示 它们而不存储转换后的字符串永远像在 StringGrid 中一样,您应该看看 Lazarus(和 Delphi)附带的标准 TDrawGrid。这个网格提供了 TStringGrid 除了字符串本身之外的所有内容。数据会在需要时转换为字符串 "on the fly",然后再次丢弃。为了显示和编辑数字,您必须实施这些事件处理程序:

  • OnDrawCell:将要在特定单元格中显示的数字转换为字符串,并将字符串绘制到网格canvas的
  • OnGetEditText,再次将数字转换为字符串,但现在用于编辑,因为该字符串将传递给单元格编辑器。
  • OnSetEditText 从单元格编辑器中获取字符串,并且必须将其转换为必须插入到数据矩阵中的数字。

下面是 DrawGrid 方法的基本代码。只需将 TDrawGrid 添加到表单并分配提到的事件处理程序。 FData 是由 CreateData 方法创建的随机数虚拟矩阵。

unit Unit1;

{$mode objfpc}{$H+}

interface

uses
  Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, Grids;

type

  { TForm1 }

  TMatrix = array of array of double;

  TForm1 = class(TForm)
    DrawGrid1: TDrawGrid;
    procedure DrawGrid1DrawCell(Sender: TObject; aCol, aRow: Integer;
      aRect: TRect; aState: TGridDrawState);
    procedure DrawGrid1GetEditText(Sender: TObject; ACol, ARow: Integer;
      var Value: string);
    procedure DrawGrid1SetEditText(Sender: TObject; ACol, ARow: Integer;
      const Value: string);
    procedure FormCreate(Sender: TObject);
  private
    FData: TMatrix;
    procedure CreateData;
    procedure PrepareGrid;
  end;

var
  Form1: TForm1;

implementation

{$R *.lfm}

{ TForm1 }

procedure TForm1.FormCreate(Sender: TObject);
begin
  CreateData;
  PrepareGrid;
end;

procedure TForm1.CreateData;
var
  r, c: Integer;
begin
  SetLength(FData, 5, 10);  // 1st index = col = x, 2nd index = row = y
  for r := 0 to High(FData[0]) do
    for c := 0 to High(FData) do
      FData[c, r] := random*100;
end;

procedure TForm1.DrawGrid1DrawCell(Sender: TObject; aCol, aRow: Integer;
  aRect: TRect; aState: TGridDrawState);
var
  s: String;
  xpos, ypos: Integer;
begin
  if (aRow = 0) and (aCol = 0) and 
     (DrawGrid1.fixedRows > 0) and (DrawGrid1.Fixedcols > 0) then
     exit;

  // Fixed row
  if (aRow = 0) and (DrawGrid1.FixedRows > 0) then begin
    s := Format('Col %d', [aCol - DrawGrid1.FixedCols]);
    xpos := (aRect.Left + aRect.Right - DrawGrid1.Canvas.TextWidth(s)) div 2;
  end else
  // Fixed col
  if (aCol = 0) and (DrawGrid1.FixedCols > 0) then begin
    s := Format('Row %d', [aRow - DrawGrid1.FixedRows]);
    xpos := (aRect.Left + aRect.Right - DrawGrid1.Canvas.TextWidth(s)) div 2;
  end else begin
    // Normal cells
    s := FormatFloat('0.000', FData[aCol-DrawGrid1.FixedCols, aRow-DrawGrid1.FixedRows]);
    xpos := aRect.Right - constCellPadding - DrawGrid1.Canvas.TextWidth(s);
  end;
  ypos := (aRect.Top + aRect.Bottom - DrawGrid1.Canvas.TextHeight('Tg')) div 2;
  // Draw cell text
  DrawGrid1.Canvas.TextOut(xpos, ypos, s);
end;

procedure TForm1.DrawGrid1GetEditText(Sender: TObject; ACol, ARow: Integer;
  var Value: string);
begin
  Value := FormatFloat('0.000', FData[ACol - DrawGrid1.FixedCols, ARow - DrawGrid1.FixedRows]);
end;

procedure TForm1.DrawGrid1SetEditText(Sender: TObject; ACol, ARow: Integer;
  const Value: string);
var
  number: Double;
begin
  if TryStrToFloat(Value, number) then
    FData[ACol - DrawGrid1.FixedCols, ARow - DrawGrid1.FixedRows] := number;
end;

procedure TForm1.PrepareGrid;
begin
  DrawGrid1.RowCount := Length(FData[0]) + DrawGrid1.FixedRows;
  DrawGrid1.ColCount := Length(FData) + DrawGrid1.FixedCols;
  Invalidate;
end;

end.