Współrzędne pikseli w StringGridzie.

0

Witam. Mam problem:
Próbuję napisać aplikację, która wyświetla współrzędne pikseli PaintBox'a, na których kliknęliśmy myszą.
Proszę o pomoc w znalezieniu błędu.
Mój program (bez względu na to ile punktów wybierzemy w ComboBox) wyświetla tylko współrzędne pierwszego i ostatniego piksela. Pełnie popełniłem jakiś błąd w pętli, ale nie widzę go.

 unit Unit1;

{$mode objfpc}{$H+}

interface

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

type

  { TForm1 }

  TForm1 = class(TForm)
    Button1: TButton;
    Button2: TButton;
    ComboBox1: TComboBox;
    PaintBox1: TPaintBox;
    StringGrid1: TStringGrid;
    procedure Button1Click(Sender: TObject);
    procedure ComboBox1Change(Sender: TObject);
    procedure PaintBox1MouseDown(Sender: TObject; Button: TMouseButton;
      Shift: TShiftState; X, Y: Integer);
  private
    { private declarations }
  public
    { public declarations }
  end;

type
  TPoint = record
    A: longint;
    B: longint;
  end;

var
  Form1: TForm1;
  POINTS_ARR: array of TPoint;
  i:integer;

implementation

{$R *.lfm}

{ TForm1 }

procedure TForm1.PaintBox1MouseDown(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer);

begin
  SetLength(POINTS_ARR,ComboBox1.ItemIndex+3);

  PaintBox1.Canvas.Pixels[X,Y]:=clRed;
  POINTS_ARR[i].A:=X;
  POINTS_ARR[i].B:=Y;
  for i:=0 to ComboBox1.ItemIndex+2 do
  begin
   StringGrid1.Cells[1,i]:=IntToStr(POINTS_ARR[i].A);
   StringGrid1.Cells[2,i]:=IntToStr(POINTS_ARR[i].B);
  end;

end;

procedure TForm1.Button1Click(Sender: TObject);
var
  liczbawierszy:integer;
begin
  liczbawierszy:=ComboBox1.ItemIndex+3;
  StringGrid1.RowCount:=liczbawierszy;
end;

procedure TForm1.ComboBox1Change(Sender: TObject);
begin

end;





end.  
0

Dlaczego za każdym razem (tj.przy każdym kliknięciu, czy raczej przeciągnięciu myszką z naciśniętym LPM) inicjujesz tę tablicę od nowa?

0

Nie bardzo rozumiem. A jak powinienem dodać wsp. pikseli do tablicy?

0

O ile się nie mylę, to powinno być to jakoś tak:
Zmienne globalne:

Var Points: Array of TPoint;
    CurrentPoint: Integer; // LongWord, Byte...

Procedury:

Procedure ZmianaElementuWComboBox;
Begin
 SetLength(Points, nowy_rozmiar_tablicy);
 CurrentPoint := 0;
End;

Procedure PaintBoxClick;
Begin
 With Points[CurrentPoint] do
 Begin
  X := Pozycja_myszki_X();
  Y := Pozycja_myszki_Y();
  DodajNowaPozycjeDoStringGrid(X, Y);
 End;

 Inc(CurrentPoint);
End;
1
unit Unit1;

interface uses
  Windows,
  Messages,
  SysUtils,
  Classes,
  Graphics,
  Controls,
  Forms,
  Dialogs,
  Grids,
  StdCtrls,
  ExtCtrls;

type
  TForm1=class(TForm)
    PaintBox1:TPaintBox;
    ComboBox1:TComboBox;
    StringGrid1:TStringGrid;
    procedure FormCreate(Sender:TObject);
    procedure ComboBox1Change(Sender:TObject);
    procedure PaintBox1MouseDown(Sender:TObject;Button:TMouseButton;Shift:TShiftState;X,Y:Integer);
    procedure PaintBox1Paint(Sender: TObject);
  private
    Tb:array of TPoint;
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.DFM}

procedure TForm1.FormCreate(Sender:TObject);
begin
  ComboBox1.Items.Text:='3'#13'4'#13'5'#13'6'#13'7';
  ComboBox1.ItemIndex:=0;
  StringGrid1.ColCount:=2;
  StringGrid1.RowCount:=2;
  StringGrid1.FixedCols:=0;
  StringGrid1.FixedRows:=1;
  StringGrid1.Cells[0,0]:='X';
  StringGrid1.Cells[1,0]:='Y';
end;

procedure TForm1.ComboBox1Change(Sender:TObject);
var I,MaxLen,TbLen:Integer;
begin
  MaxLen:=ComboBox1.ItemIndex+3;
  TbLen:=Length(Tb);
  if TbLen>MaxLen then
  begin
    SetLength(Tb,MaxLen);
    StringGrid1.RowCount:=MaxLen+1;
  end;
end;

procedure TForm1.PaintBox1MouseDown(Sender:TObject;Button:TMouseButton;Shift:TShiftState;X,Y:Integer);
var I,MaxLen,TbLen:Integer;
begin
  MaxLen:=ComboBox1.ItemIndex+3;
  TbLen:=Length(Tb);
  if TbLen<MaxLen then
  begin
    Inc(TbLen);
    SetLength(Tb,TbLen);
  end;
  for I:=TbLen-1 downto 1 do Tb[I]:=Tb[I-1];
  Tb[0]:=Point(X,Y);
  StringGrid1.RowCount:=TbLen+1;
  for I:=0 to TbLen-1 do
  begin
    StringGrid1.Cells[0,I+1]:=IntToStr(Tb[i].X);
    StringGrid1.Cells[1,I+1]:=IntToStr(Tb[i].Y);
  end;
  PaintBox1.Invalidate;
end;

procedure TForm1.PaintBox1Paint(Sender: TObject);
var I,L:Integer;
begin
  PaintBox1.Canvas.Pen.Style:=psSolid;
  PaintBox1.Canvas.Pen.Width:=1;
  L:=Length(Tb)-1;
  if L>1 then
  begin
    PaintBox1.Canvas.Pen.Color:=clGray;
    PaintBox1.Canvas.MoveTo(Tb[L].X,Tb[L].Y);
    PaintBox1.Canvas.LineTo(Tb[0].X,Tb[0].Y);
  end;
  PaintBox1.Canvas.Pen.Color:=clBlue;
  PaintBox1.Canvas.PolyLine(Tb);
  PaintBox1.Canvas.Pen.Color:=clRed;
  PaintBox1.Canvas.Brush.Style:=bsClear;
  PaintBox1.Canvas.Pen.Width:=1;
  for I:=0 to L do PaintBox1.Canvas.Ellipse(Tb[I].X-2,Tb[I].Y-2,Tb[I].X+2,Tb[I].Y+2);
end;

end.
0

A mógłbyś jeszcze napisać jak dodać te nowe pozycje do StringGrida? Trzeba dodać pętlę?

0

A odpaliłeś i sprawdziłeś jak to działa?

0

@_13th_Dragon

Mega wielkie DZIĘKI

0

Tylko że ten twój ComboBox jest wg mnie bez sensu. Wystarczy kończyć wprowadzanie podwójnym kliknięciem. Ba kod natychmiast będzie dwukrotnie mniejszy.

0

A jak to zrobić?

0

Sprawdzając Shift:TShiftState

0

A jak to zrobić?

A jakąkolwiek pomoc w swoim środowisku masz (już o Google nie wspomnę)...?

Typ TShiftState to zwykły enum (a raczej zbiór enumów):

type TShiftState = set of (ssShift, ssAlt, ssCtrl, ssLeft, ssRight, ssMiddle, ssDouble);

Może przyjmować następujące wartości:

Value Meaning
ssShift The Shift key is held down.
ssAlt The Alt key is held down.
ssCtrl The Ctrl key is held down.
ssLeft The left mouse button is held down.
ssRight The right mouse button is held down.
ssMiddle The middle mouse button is held down.
ssDouble The mouse was double-clicked.
identyfikatory są tak intuicyjne, że od razu widać, który odpowiada za podwójne kliknięcie;

Warto też sprawdzać pozycję kursora względem ostatniego punku - dzięki ustaleniu niedużego ofsetu (np. 5px) moża odrzucić dodanie punktu, który leży zbyt blisko ostatniego w macierzy; Przyda się, jeśli chce się zabezpieczyć klikanie w przypadku, gdy zamiast podwójnie kliknąć - kliknie się raz i żeby zamknąć figurę nie trzeba było nakładać ostatniego punktu; Jeśli masz z góry ustaloną ilość punktów to się takie zabezpieczenie nie przyda, a jeśli ilość punktów ustalana jest dynamicznie (czyli ich liczba zależy od widzimisię użytkownika) to może się przydać; Jeśli nie tak, to zawsze można dodatkowo zamykać figurę jakimś klawiszem (np. Enter - gdy dynamicznie wprowadzane punkty zostały ustalone, a figura nie zamknięta);

PS: Zakładam, że ten wątek jest kontynuacją wcześniejszego z wciąż nie rozwiązanym problemem wyznaczania wierzchołków figury, odczytywania i przechowywania współrzędnych wierzchołków oraz rysowania samej figury;

0

Nie bardzo wiem, jak określić liczbę punktów wielokąta badając Shift:TShiftState . Mógłby ktoś pomóc? Albo podrzucić jakiś link z przykładem (szukałem, ale nie mogę znaleźć).

0

Aktualna liczba punktów w wielokącie jest już znana (w podanym przeze mnie kodzie) i wynosi:
Length(Tb);

1 użytkowników online, w tym zalogowanych: 0, gości: 1