AndroidアプリでTStringGridを使っているんですが、VCLみたいにデフォルト枠線がなく、OnDrawCellで枠線をRect範囲で書くようにしているんですが、どうしても隙間や重なりが気になります。
VCLのような見た目を作るにはどうすればいいんですか?
【追記】
解決したいことを箇条書きに
・FMXのTStringGridの枠線をVCLのTStringGridのようにする
→おそらく各StringColumのスクロールバーの部分で各セルの隙間が出来ている
実際のコードはこれです
procedure TFM.grdd1DrawColumnCell(Sender: TObject; const Canvas: TCanvas;
const Column: TColumn; const Bounds: TRectF; const Row: Integer;
const Value: TValue; const State: TGridDrawStates);
var
drawRect: TRectF;
begin
drawRect.Top := Bounds.Top-3;
drawRect.Left := Bounds.Left;
drawRect.Bottom := Bounds.Bottom+3;
drawRect.Right := Bounds.Right+4;
grdData.Canvas.Stroke.Kind := TBrushKind.Solid;
grdData.Canvas.Stroke.Color := TAlphaColors.Black;
grdData.Canvas.Stroke.Thickness := 1;
grdData.Canvas.DrawRect(drawRect, 0, 0, [], 1);
end;
試していませんが、OnDrawColumnCellイベントではなく、
OnDrawColumnBackgroundイベントで描画した場合は、どうなりますか?
確認しました。
上記のコードのままイベントハンドラをOnDrawColumnBackgroundイベントにした場合は、各セルの縦線は表示されなくなり、横線のみ現れ(rowcountが1以降)、それも一つ前のRowCountの下線と追加したセルの上線に追加されています。
DrawRect ではなく、DrawLine を使って、セルの下側と右側とかに描画してみるのは、いかがですか?
DrawLine試しましたが、うまくいきそうではありますが、各カラムセルwidthが異なる場合やTPointFを取得するのが、なかなか柔軟性に欠ける感じがしました。
もしよろしければ、DrawLineでのコードをご教授お願いします。
以下、テスト用で使ったコードです
procedure TForm1.StringGrid1DrawColumnCell(Sender: TObject;
const Canvas: TCanvas; const Column: TColumn; const Bounds: TRectF;
const Row: Integer; const Value: TValue; const State: TGridDrawStates);
var
CellWidth, CellHeight: Integer;
Rows, Columns: Integer;
I, J: Integer;
StartPoint, EndPoint: TPointF;
begin
// セルの数とサイズを設定
Rows := StringGrid1.RowCount; // 行数
Columns := StringGrid1.ColumnCount; // 列数
CellWidth := 100; // 各セルの幅
CellHeight := 50; // 各セルの高さ
// グリッドのセルに対して線を描画
for I := 0 to Rows do
begin
// 水平線を描画
StartPoint := TPointF.Create(0, I * CellHeight);
EndPoint := TPointF.Create(Columns * CellWidth, I * CellHeight);
Canvas.DrawLine(StartPoint, EndPoint, 1, TStrokeBrush.Create(TBrushKind.Solid,TAlphaColorrec.Black)); //黒い線
end;
for J := 0 to Columns do
begin
// 垂直線を描画
StartPoint := TPointF.Create(J * CellWidth, 0);
EndPoint := TPointF.Create(J * CellWidth, Rows * CellHeight);
Canvas.DrawLine(StartPoint, EndPoint, 1, TStrokeBrush.Create(TBrushKind.Solid,TAlphaColorRec.Black)); //黒い線
end;
end;
Androidではなく、Windowsで試したのですが・・
const
TEST_COL = 20;
TEST_ROW = 80;
// FormCreate
procedure TForm1.FormCreate(Sender: TObject);
var
sCol: TStringColumn;
c, r: Integer;
begin
// 線と文字列の描画は、OnDrawColumnCellイベント・OnDrawColumnBackgroundイベントにて行うので、
// いくつか設定を変更。
StringGrid1.DefaultDrawing := False;
StringGrid1.Options := StringGrid1.Options - [TGridOption.ColLines, TGridOption.RowLines];
// StringGrid初期値設定
with StringGrid1 do
begin
BeginUpdate;
for c := 1 to TEST_COL do
begin
sCol := TStringColumn.Create(StringGrid1);
sCol.Name := 'col' + IntToStr(c);
sCol.Header := 'テスト' + IntToStr(c);
sCol.Width := 80;
AddObject(sCol);
end;
EndUpdate;
RowCount := TEST_ROW;
for r := 0 to RowCount - 1 do
for c := 0 to ColumnCount - 1 do
Cells[c, r] := Format('[%d, %d]', [c, r]);
end;
end;
// StringGrid1:DrawColumnBackgroundイベント
procedure TForm1.StringGrid1DrawColumnBackground(Sender: TObject; const Canvas: TCanvas; const Column: TColumn;
const Bounds: TRectF; const Row: Integer; const Value: TValue; const State: TGridDrawStates);
begin
// 背景描画
if (Row mod 2) = 0 then
Canvas.Fill.Color := TAlphaColorRec.White
else
Canvas.Fill.Color := TAlphaColorRec.Whitesmoke;
Canvas.FillRect(Bounds, 0, 0, AllCorners, 1.0, TCornerType.Round);
// 枠線描画
Canvas.Stroke.Kind := TBrushKind.Solid;
Canvas.Stroke.Color := TAlphaColorRec.Black;
Canvas.Stroke.Thickness := 1.0;
// 縦線
Canvas.DrawLine(PointF(Bounds.Right, Bounds.Top), PointF(Bounds.Right, Bounds.Bottom), 1.0);
// 横線
if (Row mod 5) = 4 then
Canvas.Stroke.Color := TAlphaColorRec.Red; // 5行おきに線の色を赤に
Canvas.DrawLine(PointF(Bounds.Left, Bounds.Bottom), PointF(Bounds.Right, Bounds.Bottom), 1.0);
end;
// StringGrid1:DrawColumnCellイベント
procedure TForm1.StringGrid1DrawColumnCell(Sender: TObject; const Canvas: TCanvas; const Column: TColumn;
const Bounds: TRectF; const Row: Integer; const Value: TValue; const State: TGridDrawStates);
begin
// 文字描画
Canvas.Fill.Color := TAlphaColorRec.Blue;
Canvas.FillText(Bounds, Trim(Value.AsString), True, 1.0, [], TTextAlign.Center, TTextAlign.Center);
end;
ありがとうございます。
実際にコードを試してみましたが、できそうです。後はTStringGridの枠事態とヘッダーの部分に枠線をつければ、VCL同様のUIになれそうです。
各セル座標の取得で、PointF(Bounds.Left,Bounds.Bottom)のようにできるのは、盲点でした。
非常にためになるコードを書いてくださりありがとうございます。