Größe eine Objektes ändern, Berechnung falsch, aber wie mache ich es richtig?

Für Fragen zur Programmiersprache auf welcher Lazarus aufbaut
Antworten
thosch
Beiträge: 324
Registriert: Mo 10. Jul 2017, 20:32

Größe eine Objektes ändern, Berechnung falsch, aber wie mache ich es richtig?

Beitrag von thosch »

Hallo,

ich bin dabei ein Objekt in der Größe zu andern, aber die Größenänderung funktioniert nicht wie beabsichtigt. Ich habe eine externe Grafikbibliothek dazu benutzt, hier soll es aber erst mal um die Berechnung der Koordinaten gehen, vielleicht sieht hier jemand meinen Rechenfehler, dann muss das Programm keiner von Euch am eigenen Rechner ausprobieren und braucht dann auch die Grafikbibliothek nicht.

Code: Alles auswählen

program Resizetest;

uses
  sysutils,classes,
  vipgfx,vis,tools; //Grafikroutinen

var
  pic,sprt,buffer:gfxImage;        //temporäre Bildschirmpuffer
  x,y,oldx,oldy,dx,dy: Integer;      //temporäre Variablen zum Halten der akt. Mausposition
  
  //Eigene Variablen definiert da ich unabhängig von der LCL programmiert habe 
  //Muss ja auch funktionieren, will das hinbekommen ohne LCL, persönlicher Ehrgeiz!
  
  ButtonUp,                                //Maustaste losgelassen?
  ButtonDown: Boolean;            //Maustaste gedrückt?

type

  { TResizeable }

  TResizeable = class(TComponent)
  private
    FStartX: Integer;
    FStartY: Integer;
    FDeltaX: Integer;
    FDeltaY: Integer;
    FStartPosValid: Boolean;
    FRect: TRect;
  public
    constructor Create(AOwner: TComponent);
    procedure MouseDown(X,Y: Integer);
    procedure MouseMove(X,Y: Integer);
    procedure MouseUp();
    procedure Paint;

    property StartX: Integer read FStartX;
    property StartY: Integer read FStartY;
    property DeltaX: Integer read FDeltaX write FDeltaX;
    property DeltaY: Integer read FDeltaY write FDeltaY;
    Property Rect: TRect read FRect write FRect;
  end;

{ TResizeable }

constructor TResizeable.Create(AOwner: TComponent);
begin
  inherited Create (AOwner);
  FStartPosValid := false;
  FRect.Left := 10; FRect.Right := 300;
  FRect.Top  := 10; FRect.Bottom := 200;
end;

procedure TResizeable.MouseDown(X, Y: Integer);
begin
  if mouseL then
  if not FStartPosValid then
  begin
    FStartX := X;
    FStartY := Y;
    FStartPosValid := true;
    ButtonDown := true;
    ButtonUp := false;
  end;
end;

procedure TResizeable.MouseMove(X, Y: Integer);
begin
  if mouseL then
  begin
    FDeltaX := X - FStartX;
    FDeltaY := Y - FStartY;
    FRect.Right := FRect.Right + FDeltaX; FRect.Bottom := FRect.Bottom + FDeltaY;
    
    Paint;  //Hier soll das in der Größe veränderte Rechteck gezeichnet werden
    
  end;
end;

procedure TResizeable.MouseUp();
begin
  if not mouseL then
  begin
    FStartPosValid := false;
    ButtonDown := false;
    ButtonUp := true;
  end;
end;

procedure TResizeable.Paint;
begin
  DrawBarClip(vscreen,                          //Zeichne direkt in den Bildschirm
     Rect.Left,Rect.Top,Rect.Right,Rect.Bottom, //der Rechteckbereich
     RGBA(0,255,255,255)                        //die Farbe
     );
end;

var
  Widget: TResizeable;

begin
  jpegLoad(pic,'pic.jpg');                //Lade Hintergrundbild


  InitGFXSystem(800,600,false);
  initInputSystem(gfxInputMessanger);

  setGFXwindowPos(200,100);
  getGFXwindowPos(x,y);
  logwrite(numstr(x));

  setWindowCaption('test');

  Widget := TResizeable.Create(nil);
  Widget.Paint;
  oldx := mousex; oldy := mousey;
  repeat

             dx := oldx - mousex;
             dy := oldy - mousey;

             Oldx:=mousex;
             Oldy:=mousey;
             if not ButtonUp then
             begin
               x := x - dx;
               y := y - dy;
             end;
//Die obigen Berechnungen führen leider nicht zum Erfolg

     Widget.MouseDown(mousex,mousey); //mousex, mousey sind in der Grafikbibliothek enthalten und
     Widget.MouseMove(mousex,mousey); //zeigen auf die aktuelle Mauszeigerposition
     Widget.MouseUp;

     //Eine Prozedur aus der Grafikbibliothek die ein Bild oder Sprite
     //vorgegebener Größe auf den Bildschirm zeichnet
     //Kann auch Sprites kleiner als der Bildschirmbereich zeichnen,
     //wenn das Sprite vorher mit DrawBarClip() in der Größe festgelegt,
     //aber in einen Bildpuffer gezeichnet wurde, dessen Inhalt dann mit
     //PutSpriteClip ausgegeben wird

     putspriteclip(vscreen,x,y,pic,RGBA(255,0,255,255));  //Hintergrundbild auf Bildschirm
     
     //Aber nachdem das Rechteck gezeichnet wurde

     //Grafikbibliothekspezifische Tastaturabfrage
     if keyboard[VK_SPACE] then begin minimizeGFXwindow; keyboard[VK_SPACE]:=false; end;
     if keyboard[VK_F11] then begin switchWindowed; keyboard[VK_F11]:=false; end;
     if keyboard[VK_F12] then begin switchFullScreen;keyboard[VK_F12]:=false; end;

       //getGFXwindowPos(x,y);

             updateGFXsystem;
             updateInputSystem(gfxMessanger);

  until gfxDone or keyboard[VK_ESCAPE];

//Hier noch paar vipgfx spezifische Freigaben die für mein Problem irrelevant sind
  finishGFXsystem;     
  closeInputSystem;

  freeimage(pic);
  freeimage(sprt);

  ReturnFPSstring;
end.

Thandor
Beiträge: 153
Registriert: Sa 30. Jan 2010, 18:17
OS, Lazarus, FPC: Windows 10 64Bit/ lazarus 3.0 mit FPC 3.2.2 (32Bit + 64bit)
CPU-Target: 64Bit
Wohnort: Berlin

Re: Größe eine Objektes ändern, Berechnung falsch, aber wie mache ich es richtig?

Beitrag von Thandor »

Hallo thosch,

bitte beschreibe doch mal, was das jetzige Ergebnis ist. Beim überfliegen deines Quellcodes ist mir erst mal nix aufgefallen. Wenn wir das momentane Ergebnis kennen, dann können wir auch geziehler nachschauen.

Was gibt dir mousx und mousey zurück? Die Position des Mauszeigers. Aber wie wird die angegeben? Relativ zum Bildschirm/Desktop oder relativ zum "GFX-Fenster"?

LG
Thandor

thosch
Beiträge: 324
Registriert: Mo 10. Jul 2017, 20:32

Re: Größe eine Objektes ändern, Berechnung falsch, aber wie mache ich es richtig?

Beitrag von thosch »

Wenn ich mit meiner linken Maustaste auf das Rechteck klicke, nimmt es die gesamte Bildschirmgröße ein und bleibt dann so, Verkleinern ist dann nicht mehr möglich. Das muss an der Berechnung liegen die ich vornehme. Es wird kein LCL Code verwendet, habe ich bewusst so gemacht um mit eventuell meinerseits falscher Berechnung keine LCL bedingten Seiteneffekte zu erzeugen und sicher zu stellen dass ausschließlich meine Berechnung verwendet wird.

mousex, mousey gibt die aktuellen Mauskoordinaten zurück, auch bei nicht gedrückter Maustaste. Also unabhängig von gedrückten Maustasten.

Die Mausposition wird relativ zum GFX Fenster ausgegeben.

Das GFX Fenster ist dann mein Desktop, hier ein Fenster. Wenn ich InitGFXSystem(Xres,Yres, true) gebe ist der Desktop mein gesamter Bildschirm, hier aber habe ich da false angegeben, bedeutet kein Vollbild, heißt, mein GFX Bildschirm ist ein Fenster in Windows oder Linux auf der GUI.

Benutzeravatar
Winni
Beiträge: 1577
Registriert: Mo 2. Mär 2009, 16:45
OS, Lazarus, FPC: Laz2.2.2, fpc 3.2.2
CPU-Target: 64Bit
Wohnort: Fast Dänemark

Re: Größe eine Objektes ändern, Berechnung falsch, aber wie mache ich es richtig?

Beitrag von Winni »

Hi!

Sieh mal nach Deinem MouseMove:

Du erhöht bei jedem Move FRect.Right bzw. FRect.Bottom.
Da hast Du dann ganz schnell die Größe Deines Bildschirms erreicht.
Das solltest Du nur einmal machen, nämlich bei MouseUp.


Winni

thosch
Beiträge: 324
Registriert: Mo 10. Jul 2017, 20:32

Re: Größe eine Objektes ändern, Berechnung falsch, aber wie mache ich es richtig?

Beitrag von thosch »

@winni:

Nein, leider nicht.

Funktioniert auch nicht, Außerdem sehe ich ja dann während der Mausbewegung die Größenänderung nicht.

Benutzeravatar
Winni
Beiträge: 1577
Registriert: Mo 2. Mär 2009, 16:45
OS, Lazarus, FPC: Laz2.2.2, fpc 3.2.2
CPU-Target: 64Bit
Wohnort: Fast Dänemark

Re: Größe eine Objektes ändern, Berechnung falsch, aber wie mache ich es richtig?

Beitrag von Winni »

Hi!

Aufgrund Deine fehlerhaften Berechnungen in MouseMove siehst Du sehr wohl die Größenanderung:
Größer als Dein Bildschirm!!!!

Im Detail, Dein MouseMove:

Code: Alles auswählen

FDeltaX := X - FStartX;
FDeltaY := Y - FStartY;
FRect.Right := FRect.Right + FDeltaX; 
FRect.Bottom := FRect.Bottom + FDeltaY;  
Sagen wir mal FstartX und FstartY sind 20/20

Die Maus ist bei 30/30. Du addierst 10/10 auf Rechts und Unten.

Nun ist die Maus bei 50/50. Du addierst jetzt 30/30 auf Rechts und unten.

Jetzt hast Du schon 40/40 auf Rechts und Unten addiert.
Bald hast Du die rechte Seite des Bldschirm erreicht. Und die untere.

Wenn Du es nicht glaubst dann bau mal ein Label ein und lass Dir von MausMove ausgeben:

Code: Alles auswählen

Label1.caption := IntToStr(FRect.left)+' / '+IntToStr(FRect.Top) +
                                              ' / '+IntToStr(Frect.Right)+' / '+IntToStr(FRect.Bottom);
application.ProcessMessages;

Winni

thosch
Beiträge: 324
Registriert: Mo 10. Jul 2017, 20:32

Re: Größe eine Objektes ändern, Berechnung falsch, aber wie mache ich es richtig?

Beitrag von thosch »

Ok, danke so weit. Aber wie mache ich das dann richtig?

Ich will wie in Windows selber auch mit der Mausbewegung die Größe ändern und das Ergebnis sofort sehen, wie das in Windows oder Linux GUI auch ist, wenn ich da bei einem Fenster die Größe ändere. Brett vorm Kopp!

Benutzeravatar
kupferstecher
Beiträge: 418
Registriert: Do 17. Nov 2016, 11:52

Re: Größe eine Objektes ändern, Berechnung falsch, aber wie mache ich es richtig?

Beitrag von kupferstecher »

Du musst dir die Koordinaten vom originalen Rechteck im Mouse-Down speichern und im Mouse-Move über das Delta daraus die neuen Koordinaten berechnen. Und nicht wie du es tust die jeweils aktuellen Abmaße zur Neuberechnung verwenden.

thosch
Beiträge: 324
Registriert: Mo 10. Jul 2017, 20:32

Re: Größe eine Objektes ändern, Berechnung falsch, aber wie mache ich es richtig?

Beitrag von thosch »

Meine MouseMove Methode sieht so aus:

Code: Alles auswählen

procedure TResizeable.MouseMove(X, Y: Integer);
begin
  if mouseL then
  begin
    FDeltaX := X - FStartX;
    FDeltaY := Y - FStartY;
    FRect.Right := FRect.Right + FDeltaX; FRect.Bottom := FRect.Bottom + FDeltaY;
    
    Paint;
    
  end;
end;
Ich dachte, dass ich da mit X schon die aktuelle XPosition habe und davon dann StartX, den Wert, den die Mausposition zum Zeitpunkt des Drückens der linken Maustaste (mouseL) hatte????

Da msste doch nache meinem Verständnis DeltaX der Wert sein, den ich Rect.Right hinzuaddiren muss und für die Y Position analog.

Warum ist das falach?

Wie muss ich da die Originalposition in MouseDown speichern. Ich habe das jetzt so gemacht:

Code: Alles auswählen

procedure TResizeable.MouseDown(X, Y: Integer);
begin
  if mouseL then
  if not FStartPosValid then
  begin
    FStartX := X;   //Aktuelle Mausposition zum Zeitpunkt des Drückesns der linken Maustaste
    FStartY := Y;
    FStartPosValid := true;  //Startposition bzw. maßgebliche Mausposition berechnet
    ButtonDown := true;      //Linke Maustaste ist gedrückt
    ButtonUp := false;          //und nicht losgelassen
  end;
  If FStartPosValid then //Original Rechteck Koordinaten hier ermitteln
  begin
    FRightPos := FRect.Right;
    FBottomPos := FRect.Bottom;
  end;
end;
Aber wie dann weiter?

wennerer
Beiträge: 507
Registriert: Di 19. Mai 2015, 20:05
OS, Lazarus, FPC: Linux Mint 20 Cinnamon,Lazarus 2.2.6 (rev lazarus_2_2_6) FPC 3.2.2 x86_64-linux-
CPU-Target: x86_64-linux-gtk2

Re: Größe eine Objektes ändern, Berechnung falsch, aber wie mache ich es richtig?

Beitrag von wennerer »

Hallo thosch,
wenn ich dich richtig verstehe möchtest du zur Laufzeit mit der Maus die Größe eines Objekt ändern (ziehen).
Falls das so ist kannst du dir mal meinen Selector ansehen. Wenn du dir dort im Quelltext die mouse -down, -move und -up ansiehst hilft dir das vielleicht weiter.

viewtopic.php?f=29&t=13032

Viele Grüße
Bernd

Benutzeravatar
kupferstecher
Beiträge: 418
Registriert: Do 17. Nov 2016, 11:52

Re: Größe eine Objektes ändern, Berechnung falsch, aber wie mache ich es richtig?

Beitrag von kupferstecher »

thosch hat geschrieben:
So 1. Aug 2021, 12:07

Code: Alles auswählen

procedure TResizeable.MouseMove(X, Y: Integer);
begin
   //...
    FDeltaX := X - FStartX;
    FRect.Right := FRect.Right + FDeltaX;
MouseMove wird ja sehr oft aufgerufen.
Einfaches Beispiel, beim Klick (MouseDown) ist X = 10 (= FStartX). Du bewegst die Maus nach rechts, X= 50, also FDeltaX = 40.
FRectRight:= 10 + 40 = 50. Stimmt beim ersten Aufruf von MouseMove. Beim zweiten dann
FRectRight:= 50 + 40 = 90, beim 3ten
FRectRight:= 90 + 40 = 130. Usw.
Edit: Das "explodiert" dir also.

Deswegen

Code: Alles auswählen

Procedure MouseDown
begin
  FStartX := X;
  FStartRectRight := FRect.Right;  //<-
und

Code: Alles auswählen

Procedure MouseMove
begin
    FDeltaX := X - FStartX;
    FRect.Right := FStartRectRight + FDeltaX;  //<-

thosch
Beiträge: 324
Registriert: Mo 10. Jul 2017, 20:32

Re: Größe eine Objektes ändern, Berechnung falsch, aber wie mache ich es richtig?

Beitrag von thosch »

Jauuuu, danke @Kupferstecher, so klappt es mit der Größenänderung. So wie ich es haben will.

@Bernd: Auch Deine Arbeit guck ich mir an, mal schauen wie das da gelöst worden ist. Kann nur dabei lernen.

Problem glost, Danke auch an alle die hier mit rein geguckt haben! :D

Antworten