Recent

Author Topic: Graphical object selection with mouse  (Read 10983 times)

MSC

  • Jr. Member
  • **
  • Posts: 55
Graphical object selection with mouse
« on: November 20, 2014, 08:10:28 pm »
Hey,
I have created some graphical objects (e.g. TRectangle, TCircle, etc.) and put (showed) them on a TImage canvas. When I click with the mouse (OnMouseDown) on one of these graphical objects, how can I get the name of that graphical object I´ve just selected/clicked on?
Can anybody help? Brother Google was of no help.

Thanks MSC

Lazarus 1.2.4 with FPC 2.6.4 in 32bit-mode
Windows 7 64bit

Blaazen

  • Hero Member
  • *****
  • Posts: 3241
  • POKE 54296,15
    • Eye-Candy Controls
Re: Graphical object selection with mouse
« Reply #1 on: November 20, 2014, 08:12:20 pm »
Code: [Select]
var aName: string;
begin
 aName:=TShape(Sender).Name;
Lazarus 2.3.0 (rev main-2_3-2863...) FPC 3.3.1 x86_64-linux-qt Chakra, Qt 4.8.7/5.13.2, Plasma 5.17.3
Lazarus 1.8.2 r57369 FPC 3.0.4 i386-win32-win32/win64 Wine 3.21

Try Eye-Candy Controls: https://sourceforge.net/projects/eccontrols/files/

MSC

  • Jr. Member
  • **
  • Posts: 55
Re: Graphical object selection with mouse
« Reply #2 on: November 20, 2014, 08:36:53 pm »
Hey Blaazen,
thanks for your quick reply.
Quickly testing your solution, it has confirmed my fears:
Since my mouse events are actually assigned to the image canvas, your solution will give me only that name were ever I click on the canvas .
I assume, I have to write and use mouse events also for each of my created graphical objects.
This will now take some time because I`m not that specialist in OOP.

Regards MSC

Blaazen

  • Hero Member
  • *****
  • Posts: 3241
  • POKE 54296,15
    • Eye-Candy Controls
Re: Graphical object selection with mouse
« Reply #3 on: November 20, 2014, 08:57:21 pm »
Sorry, I didn't read properly your question. All your shapes are drawn on TImage.Canvas on your own. So you have to store coordinates of all objects in some array and compare it with moue cursor coordinates. The easiest it is with rectangle:
Code: [Select]
uses types;

procedure TForm1.Image1MouseDown(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer);
var aRect: TRect;
    aPoint: TPoint;
    clicked: Boolean;
begin
  aRect:=Rect();  //coordinates of your rectangle
  aPoint:=Point(X, Y);
  clicked:=PtInRect(aRect, aPoint);
end;
Lazarus 2.3.0 (rev main-2_3-2863...) FPC 3.3.1 x86_64-linux-qt Chakra, Qt 4.8.7/5.13.2, Plasma 5.17.3
Lazarus 1.8.2 r57369 FPC 3.0.4 i386-win32-win32/win64 Wine 3.21

Try Eye-Candy Controls: https://sourceforge.net/projects/eccontrols/files/

MSC

  • Jr. Member
  • **
  • Posts: 55
Re: Graphical object selection with mouse
« Reply #4 on: November 20, 2014, 09:26:45 pm »
I already had the same idea.
instead of an array, I wanted to store my graphical objects in a TList when they are created.
So the individual coordinates of the objects are also stored in TList. With mousedown, I wanted to search the actual object in TList to get all data. Therefore I need to find out the name of the clicked graphical object, which is my problem.

circular

  • Hero Member
  • *****
  • Posts: 4471
    • Personal webpage
Re: Graphical object selection with mouse
« Reply #5 on: November 20, 2014, 11:13:56 pm »
If you draw the list from 1 to N, then you need to test from N downto 1, because the latest objects are on top. The first object to be touched is the one that is there.
Conscience is the debugger of the mind

howardpc

  • Hero Member
  • *****
  • Posts: 4144
Re: Graphical object selection with mouse
« Reply #6 on: November 20, 2014, 11:57:14 pm »
If you use TGraphicControl as ancestor for your objects, you can get them to tell you their name when clicked. You don't need to mess with mouse coordinates or control boundaries at all. Here's a very basic example:

Code: [Select]
unit mainShapeClick;

{$mode objfpc}{$H+}

interface

uses
  Classes, Forms, Controls, Graphics;

type

  { TSquare }

  TSquare = class(TGraphicControl)
  protected
    procedure Paint; override;
    procedure MouseDown(Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
      override;
  public
    constructor Create(AOwner: TComponent); override;
  end;

  { TCircle }

  TCircle = class(TGraphicControl)
  protected
    procedure Paint; override;
    procedure MouseDown(Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
      override;
  public
    constructor Create(AOwner: TComponent); override;
  end;

  TForm1 = class(TForm)
    procedure FormCreate(Sender: TObject);
  private
    sq: TSquare;
    circ: TCircle;
  end;

var
  Form1: TForm1;

implementation

{$R *.lfm}

{ TCircle }

procedure TCircle.Paint;
begin
  Canvas.Brush.Color:=Color;
  Canvas.Ellipse(ClientRect);
  inherited Paint;
end;

procedure TCircle.MouseDown(Button: TMouseButton; Shift: TShiftState; X,
  Y: Integer);
begin
  inherited MouseDown(Button, Shift, X, Y);
  (Owner as TForm).Caption:='You clicked on ' + Name;
end;

constructor TCircle.Create(AOwner: TComponent);
begin
  inherited Create(AOwner);
  SetInitialBounds(70, 70, 50, 50);
end;

{ TSquare }

procedure TSquare.Paint;
begin
  Canvas.Brush.Color:=Color;
  Canvas.FillRect(ClientRect);
  Canvas.Frame(ClientRect);
  inherited Paint;
end;

procedure TSquare.MouseDown(Button: TMouseButton; Shift: TShiftState; X,
  Y: Integer);
begin
  inherited MouseDown(Button, Shift, X, Y);
  (Owner as TForm).Caption:='You clicked on ' + Name;
end;

constructor TSquare.Create(AOwner: TComponent);
begin
  inherited Create(AOwner);
  SetInitialBounds(10, 10, 50, 50);
end;

{ TForm1 }

procedure TForm1.FormCreate(Sender: TObject);
begin
  sq:=TSquare.Create(Self);
  sq.Color:=clMoneyGreen;
  sq.Name:='Square1';
  sq.Parent:=Self;

  circ:=TCircle.Create(Self);
  circ.Color:=clSkyBlue;
  circ.Name:='Circle1';
  circ.Parent:=Self;
end;

end.


MSC

  • Jr. Member
  • **
  • Posts: 55
Re: Graphical object selection with mouse
« Reply #7 on: December 08, 2014, 03:13:30 pm »
I have created a TGraphicBase = class(TGraphicControl) and a TRectangle = class(TGraphicBase) in a separate unit. TGraphicBase contains the procedure MouseDown(Button: TMouseButton; Shift: TShiftState; X, Y: Integer);   override; as suggested by howardpc.
On my main form, I have a TImage where some of these TRectangles are created and shown.
When I run the programm and click on one of these rectangles nothing happens.
It seems that the MouseDown-event in TGraphicBase is not triggered.
What did I miss or made wrong?

Regards
MSC

Windows 7 64 bit
Lazarus 1.2.4  32 bit
FPC 2.6.4

howardpc

  • Hero Member
  • *****
  • Posts: 4144
Re: Graphical object selection with mouse
« Reply #8 on: December 08, 2014, 07:22:35 pm »
...
It seems that the MouseDown-event in TGraphicBase is not triggered.
What did I miss or made wrong?

Without seeing your code, no one can answer that question.

Syndrome

  • New Member
  • *
  • Posts: 35
Re: Graphical object selection with mouse
« Reply #9 on: December 09, 2014, 04:40:45 am »
download attached archive
it contains a form with movable shapes
« Last Edit: December 09, 2014, 05:02:31 am by Syndrome »

wildfire

  • Full Member
  • ***
  • Posts: 110
Re: Graphical object selection with mouse
« Reply #10 on: December 14, 2014, 06:13:33 am »
download attached archive
it contains a form with movable shapes

Syndrome, That's exactly what I've been looking for for one of my projects & being new to graphical programming in general I'm sure you've saved me a lot of headaches.

Thank you very much  :)
A halo is a mere circle, when does it end?

zamtmn

  • Hero Member
  • *****
  • Posts: 684
Re: Graphical object selection with mouse
« Reply #11 on: December 14, 2014, 04:26:03 pm »
Note - storage of graphical objects in a linear list is not optimal - with an increase in the number of objects performance decreases rapidly even on modern computers. if you plan to work with dozens of objects - do not worry, if thousands - it is better to use tree data structures.
I am also trying to do a similar graphical application http://forum.lazarus.freepascal.org/index.php/topic,16665.0.html and encountered this problem.

User137

  • Hero Member
  • *****
  • Posts: 1791
    • Nxpascal home
Re: Graphical object selection with mouse
« Reply #12 on: December 14, 2014, 04:40:37 pm »
This topic sides also different kind of code, if what you have is hundreds or thousands of dynamically placed points on screen, and you want to interact with them with mouse. I imagine 1 application be 3D-modelling software in polygon vertex selection mode, or a rts game. Basically circular selection of nearest object.

Code: [Select]
var // Public or class variables
  points: array of TMyObjectType;
  mouseFocus: integer;
...
// Any local procedure
const SelectRadius = 4.0;
var
  nearest, dx, dy, distSqr: single;
  j: integer;
begin
  // If nothing is focused, it will be -1
  mouseFocus:=-1;

  nearest:=SelectRadius*SelectRadius;
  for j:=low(points) to high(points) do begin
    dx:=mouseX-points[j].X;
    dy:=mouseY-points[j].Y;
    distSqr:=dx*dx+dy*dy;
    if (distSqr < nearest) then begin
      nearest:=distSqr;
      mouseFocus:=j;
    end;
  end;
end;
This is very fast algorithm in that we don't go all the way with sqrt() or hypot(). It also solves the usual problem, that if you were to use physical circle objects, some points may have very tiny selection area under some other overlapped point.

wildfire

  • Full Member
  • ***
  • Posts: 110
Re: Graphical object selection with mouse
« Reply #13 on: December 14, 2014, 08:36:08 pm »
Note - storage of graphical objects in a linear list is not optimal

I'm aware of that zamtmn, the logistics I can handle and have already improved it massively. My project would easily have 10's of thousands of graphical class instances, but Syndrome's example gives me the basics of writing on a canvas (very simple I agree having seen a simple example) and as I said I am brand new to any type of graphic programming (always having LCL components to rely on).

My thanks to Syndrome still stands.
A halo is a mere circle, when does it end?

 

TinyPortal © 2005-2018