figure shape--->canvas background

I am able to paint a figure shape onto a canvas. The intent is to move the canvas with mousedrag. Return true on mouse click. But when dragging occurs the shape only follows the canvas to the mouseY coordinate…not the mouseX. Therefore, I want to make the shape into a pic so as to make it a canvas backdrop. 1) why the drag problem 2) how to put figure shape into the background. Thanks!

Are you trying to drag the canvas? or an drawn within the canvas? would need to see the code.

Greetings,
I want to drag the canvas (w/ mousedrag) and keep the image in the canvas. I can create the figure in the assigned canvas(). I can move the canvas around ok. But the figure shape does not synch with mouseX. MouseY works fine! So I thought, force the issue and make the polygon a background to the canvas. There will be about 12 canvases floating around on the window.

Thanks Matt

draw the figureshape on the canvas graphics in the canvas’ paint event.
It will be automatically be drawn relative to the canvas.

Are you drawing the figure on the window to match the canvas position?

or - are you redrawing the image in the Canvas Paint event?

[quote=206982:@Carl Gibson]Greetings,
I want to drag the canvas (w/ mousedrag) and keep the image in the canvas. I can create the figure in the assigned canvas(). I can move the canvas around ok. But the figure shape does not synch with mouseX. MouseY works fine! So I thought, force the issue and make the polygon a background to the canvas. There will be about 12 canvases floating around on the window.[/quote]

Would you share what you got so far ?

the figure is drawn in a method that is called in a paint event of the canvas set. Based on what I see the figure appears to be going properly onto the canvas. Here is the method:

rem DrawPrism(g As Graphis, sides As Integer, rotation As single, I As integer)

Dim L As Integer
Dim J As Integer
Dim Theta, Theta1 As single
Dim X0, Y0, X1, Y1 as single
Dim P As New FigureShape
Dim Xmin, Xmax, Ymin, Ymax as single

theta=2pi/sides
L=2
size*sin(theta/2) rem length of a side to the polygon

theta1=rotation
X1=0
Y1=0

For J=0 to sides-1 Rem calculate point vertices offsets to resize the canvas to just fit the polygon
X0=X1
Y0=Y1
theta1=theta1+theta
X1=Lcos(theta1)+X0
Y1=L
sin(theta1)+Y0

if X1<Xmin then Xmin=X1
if Y1<Ymin then Ymin=Y1
if X1>Xmax then Xmax=X1
if Y1>Ymax then Ymax=Y1
Listbox1.AddRow (str(j), str(X0), str(Y0), str(X1), str(Y1))

next J
Listbox1.AddRow (“summary”, “xMin”,“yMin”,“xMax”,“yMax”) Rem to keep track of my points for debugging
Listbox1.AddRow (“summary”, str(Xmin), str(Ymin), str(Xmax), str(Ymax))

theta1=rotation
X1=-xMin
Y1=-yMin

For J=0 to sides-1 rem use the offsets
X0=X1
Y0=Y1
theta1=theta1+theta

X1=L*cos(theta1)+X0
Y1=L*sin(theta1)+Y0
P.AddLine X0, Y0, X1, Y1
Listbox1.AddRow (str(j), str(X0), str(Y0), str(X1), str(Y1)) rem allows me to track the coordinates of the points

next J

prismCanvas(i).width=2size rem or Xmax-Xmin
PrismCanvas(i).height=2
size

P.Border = 100 // opaque border code straight from documentation
P.BorderColor = &cFF0000 // red border
P.FillColor = &cFFFF00 // yellow interior
PrismCanvas(i).left=200+10*CanvasCount

g.DrawObject P

In the paint routine of the canvasSet is: It only work here. It would be very nice if I can make it work other places

drawPrism me.graphics, val(TSides.text), 50, .2, me.index
opticalBench.invalidate  rem (window)

It however will NOT work when I do the following to try to prevent extra paint events: (still in the paint event of the canvasSet)

dim i as integer

i=lastPrism
if lastPrism<>i then (lastPrism is a property-it works)
lastPrism=i rem may have clicked on a different canvas
drawPrism me.graphics, val(TSides.text), 50, .2, me.index
opticalBench.invalidate
end if

I would prefer to keep the paint event as clean of code as possible. Before all is done I want to place prisms, lenses and lasers onto the optical bench. Curiously, I have done this all in RB but as you know all for naught.
Thanks for helping!

Carl

Difficult to see what is going on from the code you posted. It is just the paint routine, and is not complete enough to draw. There are many variables that could be the source of the issue.

Maybe you are doing too much before making sure the principle is sound. Complex drawing plus control set compound possible issues.

I would go step by step and validate each step before going further.

Why not simply start by drawing a simple figure like a rectangle or a circle, and make sure the thing works first with one single canvas ?

When you are certain it works as expected with a simple drawing and a single control, then make it a control set, verify everything works as well as in the single canvas.

Then when you are comfortable the method to move the canvas and the drawing don’t interfere, you can try your more complex shape again.

I do not think wise to use code to prevent drawing. It is much too premature. Never try to optimize before a project works fully.

Finally, drawing outside of the paint event. I know you are coming from RB, which allowed that in the past. But you want to ask yourself if it is absolutely necessary. The more places you will be drawing into the canvas, the more risks of bugs. When everything is in the same place, your code is clean and the process easy to understand.

Is it not what you are doing in Paint ?

Or are you talking about placing the shape in the Backdrop property ? You can indeed do that, and even draw into it from outside paint. I posted a method there https://forum.xojo.com/24791-paint-w-o-paint-handler

At any rate, I strongly recommend a step by step approach and to keep things in the same place. For instance, if you chose the backdrop picture method, dont mess in Paint at the same time. Keep all your painting there.

Greetings, thanks for your good advice. I have gotten the code to work on a single canvas and it does draw complex polygons. Why mouseY works and mouseX does not when i drag the mouse is a mystery to me The mouse drag event is just those two commands. I put a pic in the backdrop property to make sure the canvas was being instantiating and then saw the polygon on top. I will do the backdrop strategy. However the OCD in me would like to get the other to work.

Michael, thanks again,

Cheers

Let me understand here. The polygon draws fine, dragging the canvas works fine, but yet you still get the issue with MouseX ?

Yes! I think its a system bug…not my problem

I got it to work like a charm, thanks to you and RB V4.5 documentation

previous code creates the figureshape and the appropriate sized canvas

open canvas event called from with a button that instantiates a new canvas:

canvasCount=me.index
if me.index>0 then
PrismCanvas(canvasCount).visible=true
drawPrism (val(TSides.text), 50, 0, me.index)
end if

method subroutine “drawPrism” called from within the open canvas event:

Dim buffer As New Picture (xWidth, yHeight)
Redim prism2D(Ubound(prism2D)+1)
prism2D(i)=New Group2D rem prism2D(i) is a property of the window
prism2D(i).Append Figure rem put the figure shape “Figure” into group2D “prism2D(i)”
prismCanvas(i).Backdrop=buffer rem create a picture shell for the figure shape “figure” which has already been created
prismCanvas(i).Backdrop.Objects=prism2D(i) rem put in the figureshape

in the Paint event of the prismCanvas() is:
g.DrawObject prism2D(me.index) rem this draws the polygon perfectly

in mouseDrag event, here mouseX does work! :
prismCanvas(index).left=mouseX
prismCanvas(index).top=mouseY
rem would like the mouse to stay centered on the canvas where clicked but it does not…and I can’t make it without the
canvas jumping from one left, top position to the center and back.

I do believe xoxo docs are very vague for people like me…they lack context as to from where something is called, assumed properties, and exactly where code is to be placed. The word “simply” needs to erased from their vocabulary.

I will use this to create other objects within my project (lenses, mirrors and lasers.)

Thanks again!!

If this is in the Paint event of a canvas, then you have a bug in your code. Do not use me.graphics. Use the “g” parameter passed into the event. They are not always the same context.

drawPrism g, val(TSides.text), 50, .2, me.index

Greetings,

No. This line is in several different events and a method as the size, shape and rotation of the polygon is dynamically changed. It works. Tim, Thank you for the cautionary note.

The paint event is: g.DrawObject me.prism2D

OK, just checking. Any time “me” refers to a canvas, you should never use “me.graphics”. Just fyi.

The thing is, although it is very strongly discouraged in the LR, saying that it has been deprecated, unlike accessing the UI from a thread, it still works…

To me , it feels as is you might tidy things by making a subclass of canvas, and giving that class a figureshape property of its own, instead of having some canvases and some figureshapes be part of a window.

Then each MyCanvas object would draw its own mFigureshape during its own paint event.
If the Figureshape property was public, you could still manipulate it from the window.
But better would be to give myCanvas a method that the window could call to manipulate the shape.

========

All that said, the shape should be drawing itself in relation to the canvas, not in relation to the window.
If the shape draws a circle in the middle of the canvas, it should always be in the middle of the canvas, no matter where the canvas is placed.

(Try it: instead of the complex stuff you have shown, change the paint event code for the canvas object to be:

dim r as new rectshape r.x = me.width/2 r.y = me.height/2 r.width = 20 r.height = 20 g.drawobject r

)

===========

But the thing I think is troubling you most is this:

[quote]
prismCanvas(index).left=mouseX
prismCanvas(index).top=mouseY
rem would like the mouse to stay centered on the canvas where clicked but it does not…and I can’t make it without the
canvas jumping from one left, top position to the center and back.[/quote]

If you want to move the canvas to FOLLOW the mouse, you need to take account of where in the canvas you first clicked.

Think of just the x co-ordinate for a moment.
You click on the canvas, and the mouse is at 200,100
The canvas is at 190,85
Even if you don’t move the mouse, you code immediately moves the canvas by 10 pixels to the right, because you are moving the LEFT of the canvas to meet the mouse, instead moving something in the middle of the canvas to position 190.

The difference is the x,y position within the canvas.
So you need to record where the mouse went down on the canvas.
In the case above,
mousex , mousey in the window is 200,100
x, y in the canvas was 10,15

move the mouse to 300,200
You need to move the canvas to (300 -10), (200 -15)

It may not crash your app like accessing UI from a thread, but it will produce results like the OP is reporting, which is why I suspected it. It may not be the culprit in this case, but it is capable of failing in a similar manner.

I would not know, I probably never used it, except a few minutes ago just to verify what happened. I think Xojo are to simply remove access to that property to prevent bad code to be written.