首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >StringGrid对象-访问冲突

StringGrid对象-访问冲突
EN

Stack Overflow用户
提问于 2015-07-30 10:03:34
回答 1查看 1.2K关注 0票数 0

我试图使用子代中Stringgrid的Objects属性,我认为我做错了什么。因此,我创建了一个用于我的StringGrid单元格的简单类,类似于:

代码语言:javascript
复制
type

  TKind = (tkNone,tkStart, tkEnd, tkMiddle);

  TMyCell = class(TObject)
  private
    FKind:string; // TKind: start, middle, end, none
    FOfType:string; // new, registered, paid, over, none
    FActualDate:TDate; 
    FTheText:string; // if you want to show a text in it
    FIsWeekend:Boolean;
    function IsItWeekend(dt:Tdate):boolean;
    procedure setKind(s:string);
    { Private declarations }
  protected
    { Protected declarations }
  public
    constructor Create;
    property Kind:string read FKind write setKind;
    property OfType:string read FOfType write FOfType;
    property ActualDate:TDate read FActualDate write FActualDate;
    property TheText:string read FTheText write FTheText;
    property IsWeekend:Boolean read FIsWeekend write FIsWeekend default false;
    { Public declarations }
  published
    { Published declarations }
  end;


implementation

procedure TMyCell.setKind(s:string);
begin
  FKind:=s;
end;

function TMyCell.IsItWeekend(dt:Tdate):boolean;
begin
  if (DayOfTheWeek(dt)=6) or (DayOfTheWeek(dt)=7) then IsItWeekend:=true else IsItWeekend:=false;    
end;

constructor TMyCell.Create;
var
  i:integer;
  a,l,z:word;
  dt:TDate;
begin
  FKind:='none';
  FOfType:='none';
  FActualDate:=now;
  FTheText:='';
  FIsWeekend:=IsItWeekend(FActualDate);
end;

然后,在我的StringGrid后代(TMyGrid)中,我执行以下操作:

代码语言:javascript
复制
 TMyGrid = class(TStringGrid)
  private
    FStartSelection:integer;
    FFixedColor:TColor;
    FRowCount:integer;
  ...
  published
    property ColCount;
    property RowCount;
  ...

constructor TMyGrid.Create(AOwner: TComponent);
var
  i:integer;
  a,l,z:word;
  dt:TDate;
  j: Integer;
  myCell:TMyCell;
begin
  inherited;
  ...// different settings
  RowCount:=5;
  for i := 0 to colCount-1 do
    for j := 0 to RowCount-1 do
      begin
        Objects[i, j] := TMyCell.Create;
      end;
end;

destructor TMyGrid.Destroy;
var
  i,j:integer;
begin
  for i := 0 to colCount-1 do
    for j := 0 to RowCount-1 do
      begin
        TMyCell(Objects[i, j]).Free;
      end;
  inherited;
end;

... // other stuff

procedure Register;
begin
  RegisterComponents('mygrid', [TMyGrid]);
end;

问题是,我不知道如何告诉我的控件,当开发人员在运行应用程序之前更改RowCount中的objectInspector时,会有更多的行。因此,我将StrinGrid后代放在窗体上,并将rowCount设置为10。但是,我的StringGrid没有为新行创建对象,因此ARow=5->9上的单元格没有创建对象.因为在OnCreate中,我只将RowCount的初始值设置为5,并为i:=0创建对象为RowCount-1。

是否有一个事件或方法可以让StringGrid在开发人员更改ObjectInspector中的rowCount之后创建对象?

我确信这是我的问题,因为使用上面的代码,当我将stringGrid放在表单上并将其设置为rowCount (设计时或运行时)为10时,我想将一个值赋给Row>4上单元格的Row>4属性,我会得到一个AccessViolation,但是如果我对一个行(即<= 4)这样做,分配就会很好。

我在这里找到了一些应该有用的东西:http://embarcadero.newsgroups.archived.at/public.delphi.ide/200904/0904193279.html,但我不知道如何将这些代码放在StringGrid子类中,以便在设计时/运行时更改RowCount时调用它。

编辑

在阅读了您的评论之后,我尝试了您的想法(这似乎有效)来覆盖SizeChanged (我不知道存在该方法,一定是在我之前讲课时跳过的)。总之,我把这段代码添加到了我的课堂上:

代码语言:javascript
复制
TMyGrid = class(TStringGrid)
  private
    ...
    procedure SizeChanged(OldColCount, OldRowCount: Longint); override;
    procedure UpdateGridDimensions(NewColCount, NewRowCount: Integer);
    ...

procedure TMyGrid.SizeChanged(OldColCount, OldRowCount: Longint);
begin
  inherited;
  if (OldRowCount<>FRowCount)or(OldColCount<>ColCount) then
    UpdateGridDimensions(ColCount, FRowCount);
end;


procedure TMyGrid.UpdateGridDimensions(NewColCount, NewRowCount: Integer);
 var
    C, R: Integer;
    Old: Integer;
 begin
    if NewColCount <> ColCount then
    begin
        if NewColCount < ColCount then
        begin
            for R := 0 to RowCount-1 do
            begin
                for C := ColCount-1 downto NewColCount do
                    Objects[C, R].Free;
            end;
        end;

        Old := ColCount;
        ColCount := NewColCount;

        if NewColCount > Old then
        begin
            for R := 0 to RowCount-1 do
            begin
                for C := Old to NewColCount-1 do
                    Objects[C, R] := TMyCell.Create;
            end;
        end;
    end;

    if NewRowCount <> RowCount then
    begin
        if NewRowCount < RowCount then
        begin
            for C := 0 to ColCount-1 do
            begin
                for R := RowCount-1 downto NewRowCount do
                    Objects[C, R].Free;
            end;
        end;

        Old := RowCount;
        RowCount := NewColCount;

        if NewRowCount > Old then
      begin
            for C := 0 to ColCount-1 do
            begin
                for R := Old to NewRowCount-1 do
                    Objects[C, R] := TMyCell.Create;
            end;
        end;
    end;
 end;

但现在每当我把控制放在表单上时,行数是93.我该把那个rowCount设置在哪里?因为我没有。

但是,如果我将RowCount从93增加到100,那么我的对象存在于前93行,但是它们不会为93-100行创建.

所以这个主意听起来很棒,但不像我想象的那样.

有什么想法吗?我做错了吗?

EN

回答 1

Stack Overflow用户

发布于 2015-07-30 11:05:58

代码语言:javascript
复制
// SizeChanged - Called when the size of the grid has changed.
protected
  procedure SizeChanged(OldColCount, OldRowCount: Longint); dynamic;

您可以重写动态方法SizeChanged并根据新大小初始化网格。您可以检查它的设计时间是否(路suggested链接)。正如David提到的,最好为组件的使用者保留Objects属性。创建并使用您自己的TList/TObjectList。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/31720773

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档