1

私は12の形を持っています

Shape1
Shape2
.....
Shape12

12個のラベルがあります

Label13
Label14
......
Label24

このような関数を作成する方法があるかどうか疑問に思っていました。マウスで図形を入力すると、対応するラベルが別のラベルに割り当てられます。たとえば、Label25:

Label25 :=  
OnMouseEnter
shape1 -> label13
shape2 -> label14
...
shape12 -> label24

したがって、マウスが Shape1 に入ると、Label25 は Label13 と等しくなり、マウスが Shape2 に入ると、Label25 は Label14 と等しくなり、マウスが Shape12 に入ると、Label25 は Label24 と等しくなります。

私は書くことができることを知っています

label25 := labelxx 

各マウス入力イベントで。しかし、ラベルの名前と形状が対応しているため、より簡単な方法があると考えました。ここで、ラベル番号は形状番号よりも 12 大きくなっています。

提案を追加した後、これを追加しました

procedure TFZone1Mod7.ChangeText(sender: TObject);
var
  ShapeOrderNo: integer;
  FoundComponent: TComponent;
begin
  if TryStrToInt(copy(TShape(Sender).Name,6,MaxInt),ShapeOrderNo) then
    begin
      FoundComponent := FindComponent('label'+inttostr(ShapeOrderNo+12));
      if (FoundComponent is TLabel) then
            Label25.Caption := TLabel(FoundComponent).Caption
      else
          showmessage('not found');
    end;
  showmessage('failed try');

end;

procedure TFZone1Mod7.Shape1MouseEnter(Sender: TObject);
begin
    changetext(self);
end;

end.

しかし、実行されるたびに失敗してしまいます。情報を間違って送信していますか?

4

4 に答える 4

6

この種のデザインは好きではありませんが、すべての図形に共通のイベントハンドラーを使用し、FindComponent関数を使用してそこで名前でコンポーネントを見つけることができます。次に、次のようなものを書くことができます(テストされておらず、ブラウザだけで書かれていることに注意してください)。

var
  ShapeOrderNo: Integer;
  FoundComponent: TComponent;
begin
  // first try to convert a text behind "Shape", what should be a shape's order 
  // and if it's convertable to integer, then...
  if TryStrToInt(Copy(TShape(Sender).Name, 6, MaxInt), ShapeOrderNo) then
  begin
    // try to find a component with the name "label" + found shape order number
    // incremented by 12
    FoundComponent := FindComponent('label' + IntToStr(ShapeOrderNo + 12));
    // if the component is found, or to be more specific, if it's TLabel, then...
    if (FoundComponent is TLabel) then
      TLabel(FoundComponent).Caption := 'Hello from ' + TShape(Sender).Name;
  end;
end;
于 2012-10-19T07:18:08.280 に答える
2

TShape にプロパティを追加します。

 TMyShape= class(TShape)
 private
   FLinkLabel: TLabel;
 procedure SetLinkLabel(const Value: TLabel);
 published
   property LinkLabel: TLabel read FLinkLabel write SetLinkLabel;
 end;

 procedure TMyShape.SetLinkLabel(const Value: TLabel);
 begin
   FLinkLabel := Value;
 end;

 procedure TForm1.FormCreate(Sender: TObject);
 var
   oMyShape: TMyShape;
 begin
   oMyShape:= TMyShape.Create(self);
   oMyShape.Parent:= Self;
   oMyShape.LinkLabel:= self.Label1;
   oMyShape.OnMouseEnter:= OnShapeMouseEnter;
 end;

 procedure TForm1.OnShapeMouseEnter(Sender: TObject);
 begin
   if (sender is TMyShape) and
      ( TMyShape(Sender).LinkLabel <>Nil) then
   begin
     TMyShape(Sender).LinkLabel.Caption:= 'Hello';
   end;
 end;

フォームに tlabel を設定し、ラベルを TMyShape にリンクするだけです。

于 2012-10-19T08:04:07.013 に答える
2

ラベルの作成を書き直したくない場合は、findcomponent を使用します。

すべての形状に同じハンドラ

procedure TForm1.Shape1MouseEnter(Sender: TObject);
var
  ActiveShape: TShape;
  StrName: string;
  ActiveLabel: TComponent;
begin
  if Sender is TShape then
  begin
    ActiveShape := TShape(Sender);
// Only works if Shapes are named Shape1..12 and the labels Label1..12 !!
    StrName := 'Label' + copy(ActiveShape.name, 6, length(ActiveShape.name)); 
    ActiveLabel := FindComponent(StrName);
    if ActiveLabel is TLabel then
      Label25.Caption := TLabel(ActiveLabel).Caption;
  end;
end;

これは、少し面倒な場合に必要なことを行います:)

[編集] これを改善し、別の「name_number」を持つラベルの必要性を満たす簡単な方法があることに気づきました。

デザイナで、各 TShape の Tag プロパティを関連付けるラベル番号に設定します。そのため、シェイプ ワンのタグを 13 に設定します (質問にとどまるために)。

procedure TForm1.Shape1MouseEnter(Sender: TObject);
var
  ActiveShape: TShape;
  StrName: string;
  ActiveLabel: TComponent;
begin
  if Sender is TShape then
  begin
    ActiveShape := TShape(Sender);
    StrName := 'Label' + IntToStr(ActiveShape.Tag); // find tag numbered label
    ActiveLabel := FindComponent(StrName);
    if ActiveLabel is TLabel then
      Label25.Caption := TLabel(ActiveLabel).Caption;
  end;
end;
于 2012-10-19T11:21:29.847 に答える
2

Forms Designer でコントロール管理を行わず、実行時に作成する場合は、次のようにします。

ラベルの配列と形状の配列を宣言します。

const
  ShapesCount = 20;

type
  TForm1 = class(TForm)
    fLabels: array [0..ShapesCount-1] of TLabel;
    fShapes: array [0..ShapesCount-1] of TShape;

Tag実行時に、各形状にそのインデックスを割り当てます。

procedure TForm1.OnFormCreate;
begin
  for I := 0 to ShapesCount - 1 do  
  begin
    fShapes[I] := TShape.Create(..);
    fLabels[I] := TLabel.Create(..);
    fShapes[I].Tag := I;
    fShapes[I].OnMouseEnter := OnShapeMouseEnter;
  end;
end;

次に、次のように使用できます。

procedure TForm1.OnShapeMouseEnter(Sender: TObject);
begin
  Assert(Sender is TShape);
  Label25.Caption := fLabels[TShape(Sender).Tag].Caption;
end;

編集: もう少し調べてみると、Lable.Captions の配列が既にあるので、そこから直接 Label25.Caption を取得できます。

于 2012-10-19T08:16:29.993 に答える