Skocz do zawartości

[Delphi]Grafika wektorowa


Akardo

Polecane posty

Witam serdecznie

 

Program ma być ,,w zasadzie" bardzo prosty dodawanie kilku figur(kwadrat koło itp) usuwanie figur ,kopiowanie, zmiana rozmiaru przesuwnie ich z jednego miejsca na drugie za pomocą myszki. Czy dobrym rozwiązaniem będzie korzystanie z Canvasa? Czy korzystać z paintboxa jeżeli nie to z jakiego komponentu? Jak zaznaczyć dany obiekt aby można było na nim wykonywać podane wyżej operacje? Mam nadzieję ze wyraziłem się w miarę jasno :)

Link do komentarza
Udostępnij na innych stronach

Ja się dopiero uczę, więc nie wiem jak to zrobić najlepiej(a nawet dobrze), ale napiszę jak ja bym to zrobił i lepiej poczekaj na jak ktoś kto się zna Ci odpowie :P

Jak program ma być prosty to chyba Canvasa wystarczy a w paintboxie też się chyba używa canvasa, ale głowy nie daję.

Zaznaczyć można na przykład tak(prostokąt):

if (X >= FPosX)and(X <= FPosX+FWidth)and(Y >= FPosY)and(Y <= FPosY+FHeight)then FSelect:= True; { X, Y – położenie myszki; FPosX, FPosY – left I top figury; FWidth, FHeight – wymiary figury}

Działa, ale pewnie są lepsze sposoby ;)

Zaznaczyć koło to pewnie jeśli odległość wskaźnika myszki od środka koła jest mniejsza niż promień koła to zaznacz :)

Link do komentarza
Udostępnij na innych stronach

Jak najprościej to tak jak Ci powiedzieli. Napisz kilka metod do wykrywania czy punkt znajduje się w prostokącię, kole, okręgu (z jakas tolerancją niewielką powiedzmy)

 

Potem w MouseDown wykrywasz kolizję obiektów z kursorem myszy. A w MouseMove sprawdzasz czy jest jakiś obiekt oznaczony flagą zaznaczenia i czy jest dodatkowo w wciśnięty lewy myszy. Wtedy przesuwasz zaznaczony objekt względem kursora.

 

Wyświetlanie to sobie zorganizuj jak Tobie wygodniej jest i prościej.

Ot taka mini-strona moja po godzinach :)http://www.wnetrzekuchni.pl

Link do komentarza
Udostępnij na innych stronach

Jest jeszcze komponent "Shape1: TShape;" można by było go chyba dynamicznie tworzyć ruszać, skalować itd.

Edit: Przechowuje kształt figury, kolory i wszystko czego potrzeba. Ma wbudowane zdarzenia Shape1MouseDown itd. więc mniej roboty chyba by było :)

Edit2: Na TShape chyba najlepiej wyjdzie (trochę próbowałem), ale Drag/Dock/Drop nie ogarniam, bo chyba tak można sobie przesuwać wszystko jak inne komponenty:)

Link do komentarza
Udostępnij na innych stronach

 if (X >= FPosX)and(X <= FPosX+FWidth)and(Y >= FPosY)and(Y <= FPosY+FHeight)then FSelect:= True; { X, Y – położenie myszki; FPosX, FPosY – left I top figury; FWidth, FHeight – wymiary figury}        -Ż)ŚrŚ+^J\"7ŹgóĘźŹŁŚjghŚZ&ĘhwzZaYHL]PXĘ[X
NKLKL[YY[N[
Y]K^
N[
Y]^
NLN[
Y]^
NL[
Y]
^
NZ[K[[JKLKLN[

dane pobieram z editow no i powiem ze różne dziwne rzeczy mi wychodzą:) jakie wartości powinny mieć zmienne żeby rysowało mi te np. kolo w podanym przeze mnie rozmiarze i aby mieściiło się ono w moim paintboxie i było mniej więcej po środku:)

Link do komentarza
Udostępnij na innych stronach

Jak nie możesz ogarnąć gdzie jest środek i jak to rysować to w mspaintcie jak rysujesz elipsie (x1,y1) to punkt w którym naciskasz myszkę a (x2,y2) to punkt w którym puszczasz. Prościej mówiąc to (x1,y1) to lewa górna krawędź a (x2,y2) to prawa dolna prostokąta w który wpisana jest twoja elipsa.

Środek to punkt (x1+(x2-x1)div 2, y1+(y2-y1)div 2) :)

Zapomniałem dodać że liczy się te parametry od początku PaintBoxa, więc jeśli BP jest ustawiony left:= 100, Top:= 100; to zacznie elipse rysować od tego punktu

[Edit2: Co ja popisałem ;)]"PaintBox1.Canvas.Ellipse(x1+PaintBox1.Left, y1+PaintBox1.Top, x2+PaintBox1.Left, y2+PaintBox1.Top);" - rzeczywiste położenie elipsy na ekranie XD

Edit: krawędź - chodziło mi o narożnik(nie pamiętam jak to się matematycznie nazywało ;) )

Link do komentarza
Udostępnij na innych stronach

No i gitara mniej wiecej zamierzony efekt osiagnięty :) Teraz sie męcze z tym zaznaczaniem i przemieszczaniem obiektu kod do tego mam podac w onMouseDown buttona rysującego czy paint boxa? próbowałem wstawiać pod buttona ale nie wiem gdzie zadeklarowac fselect. Dzięki za pomoc;) i sory za moją nieudolność ale to naprawde jak naarzie dla mnie głęboka woda;)

Link do komentarza
Udostępnij na innych stronach

Może tak będzie lepiej, tylko nie kopiuj ;)

 unit Unit1;

interface

uses
 Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
 Dialogs, StdCtrls, Buttons, ExtCtrls;

type
 TForm1 = class(TForm)
   procedure FormMouseMove(Sender: TObject; Shift: TShiftState; X,
     Y: Integer);
   procedure FormCreate(Sender: TObject);
   procedure FormMouseDown(Sender: TObject; Button: TMouseButton;
     Shift: TShiftState; X, Y: Integer);
   procedure FormMouseUp(Sender: TObject; Button: TMouseButton;
     Shift: TShiftState; X, Y: Integer);
 private
   { Private declarations }
 public
   { Public declarations }
 end;

var
 Form1: TForm1;
 X1, Y1, W1, H1, dx, dy : Integer;  // Dla przykladu zmienne globalne,
 Select : Boolean;                  // nawet nie tablice
                                    // W1 - szerokosc, H1 - wysokosc
implementation

{$R *.dfm}

procedure TForm1.FormMouseMove(Sender: TObject; Shift: TShiftState; X,
 Y: Integer);                         // zdarzenie poruszenia myszką
 var
   i : Integer;
 begin
   Form1.Repaint;                    // odswierz ekran
   if Select then                    // jesli figura zaznaczona
     begin                           // to
       X1:= X-dx;     // pozycja figury=pozycja myszki
       Y1:= Y-dY;    // - punkt w ktorym zlapalismy, czy jak to nazwac?
     end;                     // możesz na razie bez dx i dy 
   Form1.Canvas.Rectangle(X1, Y1, X1+W1, Y1+H1); // Rysuj
 end;

procedure TForm1.FormCreate(Sender: TObject);
begin
 X1:= 100;  // dane poczatkowe
 Y1:= 200;
 W1:= 100;
 H1:= 100;
end;

procedure TForm1.FormMouseDown(Sender: TObject; Button: TMouseButton;
 Shift: TShiftState; X, Y: Integer);
 begin
   If (X >= X1)and(X <= X1+W1)and(Y >= Y1)and(Y <= Y1+H1)then 
      begin
          Select:= True;   //zaznacz
          dx:= X-X1;  // ustal dx i dy
          dy:= Y-Y1;
      end;
 end;

procedure TForm1.FormMouseUp(Sender: TObject; Button: TMouseButton;
 Shift: TShiftState; X, Y: Integer);
 begin
   Select:= False;   // odznacz
 end;

end.

Link do komentarza
Udostępnij na innych stronach

Dalej mi to nie wychodzi;/ próbowałem robić tak jak napisałeś efekt był taki ze po najechaniu myszka na pole paintboxa figura znikała kasowałem repainta to nic sie nie dało robić(znaczy się z moją figura) kod pisałem w formie w eventsach. Może coś namieszałem w zmiennych dam kod to powiesz moze jak mam sie do tego zabrac

 unit Unit2;

interface

uses
 Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
 Dialogs, Menus, ExtCtrls, StdCtrls, ComCtrls, TabNotBk;

type
 TForm2 = class(TForm)
   MainMenu1: TMainMenu;
   Plik1: TMenuItem;
   Otworz1: TMenuItem;
   Zapisz1: TMenuItem;
   Wyjcie1: TMenuItem;
   Edycja1: TMenuItem;
   kopiuj1: TMenuItem;
   wklej1: TMenuItem;
   wytnij1: TMenuItem;
   PageControl1: TPageControl;
   TabSheet1: TTabSheet;
   TabSheet2: TTabSheet;
   TabSheet3: TTabSheet;
   Button1: TButton;
   Edit1: TEdit;
   Edit2: TEdit;
   Edit3: TEdit;
   Edit4: TEdit;
   PaintBox1: TPaintBox;
   Label1: TLabel;
   Label2: TLabel;
   Label3: TLabel;
   Label4: TLabel;
   label5: TLabel;
   Button2: TButton;
   Button3: TButton;
   Edit5: TEdit;
   Edit6: TEdit;
   Edit7: TEdit;
   Edit8: TEdit;
   Label6: TLabel;
   Label7: TLabel;
   Label8: TLabel;
   Label9: TLabel;
   Label10: TLabel;
   Label11: TLabel;
   Button4: TButton;
   Button5: TButton;
   Edit9: TEdit;
   Edit10: TEdit;
   Edit11: TEdit;
   Edit12: TEdit;
   procedure Wyjcie1Click(Sender: TObject);
   procedure Button1Click(Sender: TObject);
   procedure Button2Click(Sender: TObject);
   procedure Button3Click(Sender: TObject);
   procedure Button4Click(Sender: TObject);
   procedure Button5Click(Sender: TObject);







 private
   { Private declarations }
 public
   { Public declarations }
 end;

var
 Form2: TForm2;

implementation

{$R *.dfm}

procedure TForm2.Button1Click(Sender: TObject);
var
x1,x2,y1,y2:integer;
begin
x1:=strtoint(edit1.text);
x2:=strtoint(edit2.text);
y1:=strtoint(edit3.text);
y2:=strtoint(edit4.text);
PaintBox1.Canvas.Ellipse(x1+PaintBox1.left, y1+PaintBox1.Top, x2+PaintBox1.left, y2+PaintBox1.Top)
end;








procedure TForm2.Button2Click(Sender: TObject);
begin
paintbox1.refresh;
end;

procedure TForm2.Button3Click(Sender: TObject);
var
x1,x2,y1,y2:integer;
begin
x1:=strtoint(edit5.text);
x2:=strtoint(edit6.text);
y1:=strtoint(edit7.text);
y2:=strtoint(edit8.text);
PaintBox1.Canvas.rectangle(x1+PaintBox1.left, y1+PaintBox1.Top, x2+PaintBox1.left, y2+PaintBox1.Top)
end;

procedure TForm2.Button4Click(Sender: TObject);
begin
paintbox1.refresh;
end;

procedure TForm2.Button5Click(Sender: TObject);
var
x1,x2,y1,y2:integer;
begin
x1:=strtoint(edit9.text);
x2:=strtoint(edit10.text);
y1:=strtoint(edit11.text);
y2:=strtoint(edit12.text);
PaintBox1.Canvas.moveto(x1+PaintBox1.left, y1+PaintBox1.Top);
PaintBox1.Canvas.LineTo(x2+PaintBox1.left, y2+PaintBox1.Top);
end;

procedure TForm2.Wyjcie1Click(Sender: TObject);
begin
close;
end;

end.

Link do komentarza
Udostępnij na innych stronach

Nie bardzo rozumiem, nie widzę kodu zaznaczania/przesuwania a poza tym nie wiem czy da się to zrobić na zmiennych lokalnych buttonów, bo żeby przesunąć figury musisz zmienić ich x1, x2, y1, y2 a jeśli są to zmienne lokalne to nie wiem jak to zmienić w innym miejscu. Jak na razie to rysujesz wszystko jak w paincie, nie da się praktycznie nic z tym zrobić. Jak chcesz przesuwać, skalować i takie tam to chyba musisz dynamicznie je rysować. Zmienne zadeklarować jako tablice i co chwilę, albo zmianę "wyczyścić" paitboxa i narysować je od nowa a twoje x1, y1, x2, y2 są jednorazowe :)

 

mi działa, nie wiem jak załącznik wysłać, ale mam pętle rysującą:

procedure TForm1.Timer1Timer(Sender: TObject);
 var
   i : Integer;
 begin
   PaintBox1.Repaint;
   If  IloscObiektow > 0 then
     begin
       i:= 1;
       while(i <= IloscObiektow)do
         begin
           if Status[i] then
             begin
               if Ksztalt[i] = 'Elipsa' then
                 PaintBox1.Canvas.Ellipse(X1[i],Y1[i],X2[i],Y2[i]);
               if Ksztalt[i] = 'Prostokat' then
                 PaintBox1.Canvas.Rectangle(X1[i],Y1[i],X2[i],Y2[i]);
               if Ksztalt[i] = 'Linia' then
                 begin
                   PaintBox1.Canvas.MoveTo(X1[i],Y1[i]);
                   PaintBox1.Canvas.LineTo(X2[i],Y2[i]);
                 end;
             end;
           Inc(i);
         end;
     end;
 end;

Nie jestem pewien czy to jest dla Ciebie jasne, ale jak chcesz wykonywać jakieś zadania po kliknięciu myszką na Paintbox to:

- klikasz raz na paintbox żeby go zaznaczyć

- na dole po lewo jest inspektor obiektów, klikasz na zakładkę 'Events' i masz tam listę zdarzeń

np:

OnMouseDown - wciśnięcie przycisku myszki

OnMouseMove - poruszanie myszką po paintboxie

OnMouseUp - puszczenie wciśniętego wcześniej przycisku myszki

- klikasz 2 razy na okienko(możesz też wybrać swoją procedurę, ale mniejsza o to) po prawo od wybranego zdarzenia i automatycznie w tworzy Ci się deklaracja funkcji i puste ciało w implementation

- teraz wpisujesz pomiędzy begin i end co ma się z okazji tego zdarzenia stać :)

Link do komentarza
Udostępnij na innych stronach

Nigdy nie korzystałem z PaintBoxa, ale ja bym spróbowal tak jak poniżej. W oryginale procedura PaintBoxToBitmap

zapisywała z TWinControl i ją w swoich programach wykorzystałem, a kod przerobiłem ze znalezionego w google.

//...
procedure TForm1.WczytajBtnClick(Sender: TObject);
var
 Jpg : TJpegImage;
begin
 OpenDialog.Filter := 'Pliki JPG|*.jpg;*.jpeg';
 if OpenDialog.Execute then
 begin
   OpenDialog.InitialDir := ExtractFilePath(OpenDialog.FileName);
   Jpg := TJPEGImage.Create;
   try
     Jpg.LoadFromFile(OpenDialog.FileName);
     PaintBox1.Canvas.Draw(0, 0, Jpg);
   except
     ShowMessage('Plik: ' + OpenDialog.FileName + ' nie jest prawidlowym JPG!');
   end;
     Jpg.Free;
 end;
end;

procedure TForm1.ZapiszBtnClick(Sender: TObject);

 procedure PaintBoxToBitmap(SourceControl : TPaintBox; DestBitmap : TBitmap);
 var
   Dest, Src : TRect;
 begin
   Src := Rect(SourceControl.Left, SourceControl.Top, SourceControl.Left + SourceControl.Width, SourceControl.Top + SourceControl.Height);
   Dest := Rect(0, 0, SourceControl.Width, SourceControl.Height);
   DestBitmap.Width := SourceControl.Width; ;
   DestBitmap.Height := SourceControl.Height;
   DestBitmap.Canvas.CopyRect(Dest, Canvas, Src);
 end;

var
 Bmp : TBitmap;
 Jpg : TJpegImage;
begin
 Bmp := TBitmap.Create;
 Jpg := TJpegImage.Create;
 PaintBoxToBitmap(PaintBox1, Bmp);
 Jpg.Assign(Bmp);
 Bmp.Free;
 Jpg.SaveToFile('D:\wynik.jpg');
 Jpg.Free;
end;

Pozdrawiam: olesio

Link do komentarza
Udostępnij na innych stronach

Oj takie podstawy. Nie napisałem o tym nawet bo myślałem, że to oczywiste, a jak nie to sobie przecież do helpa możesz

zajrzeć - nikt Tobie nie broni tego przecież zrobić. Wystarczyło tam przeczytać, że typ TJpegImage wymaga modułu jpeg.

Pozdrawiam: olesio

Link do komentarza
Udostępnij na innych stronach

Więc popraw, aby działało.

 

Proponuje poczytać o podwójnym buforowaniu.

 

Jak kolega będzie pytał o takie podstawy, to w końcu któryś z administratorów nie wytrzyma...

 

Od czego jest google? Ja używam go, do rozwiązywania problemów. Można znaleźć odpowiedzi na wiele pytań.

 

Kolega pierwszy nie pisze takiej aplikacji.

 

Pozdrawiam!

Link do komentarza
Udostępnij na innych stronach

Próbuje napisać kod usuwający element z tablicy(sprawa jest tego typu ze chce usuwac figure z paint boxa figura jest przypisana do tablicy), a wiec zaznaczam figurę klikam na button i usuwam. Zaznaczanie mam zrobione tylko mam problem z usunieciem elementu

 procedure TForm2.BitBtn2Click(Sender: TObject);
var
   i : Integer;

begin
i:=0;
if i=i then
i:=i+1;
Status[i]:=False;

end;

coś takiego usuwa mi pierwszy dodany element a potem juz lipa próbowałem dołożyć do tego pętle for ale niestety sie nie udało czytałem tez o ZeroMemory ale to chyba czyści cała tablice

Link do komentarza
Udostępnij na innych stronach

Może tak da radę zrobić?

 // usuwanie 
StatusFigury[IdZaznaczonejFigury]:= False;
// tworzenie
for i:=1 to IloscFigur do
  begin
     if not StatusFigury[i] then
        begin
           {tworzenie, przypisywanie nowych zmiennych do figury[i]}
           StatusFigury[i]:= not StatusFigury[i];
           Break;
        end;
     if i=IloscFigur then
        begin
            Inc(IloscFigur);  
            SetLength(figury, IloscFigur);
            {tworz figure[iloscFigur]}
            StatusFigury[IloscFigur]:=True;
            Break;
        end;
   end;
// Wątpie czy to by działał, bo pisałem bez delphi, ale tak dla pokazania jak bym to zrobił, przydało by się jescze dodać skracanie tablic

rysowanie i inne czynności wykonywane są na figurach, które mają StatusFigury[n]=True,

jeśli doda się figurę to znajdzie wole miejsce w tablicy, a jeśli nie ma wolnych miejsc to trzeba poszerzyć tablice (SetLength),

Jak skracać tablicę po za SetLength nie mam pojęcia

Link do komentarza
Udostępnij na innych stronach

Zarchiwizowany

Ten temat jest archiwizowany i nie można dodawać nowych odpowiedzi.

×
×
  • Utwórz nowe...