Help with graphics, please

I have a 31 canvases on my page. I created a subclass of canvas and the set the 31 up as a Control Set. I use the Activate Event Handler to fill the Canvases with a color. All the canvases are 20px from the top of the window, but I find that I have to put this:

g.ForeColor = App.DarkGray g.FillRect(0,20,me.Width,me.Height)
to paint the canvases where they actuall are. If I make the y axis 0, the painted area starts at the top of the page. Am I doing something wrong, or is this expected behaviour. The x axis is correct.

You can’t paint in the Activate event, it has to be in the Paint event - I assume this is what you meant.

Your code:

g.ForeColor = App.DarkGray g.FillRect(0,20,me.Width,me.Height)
belongs into the canvas’ Paint event, not the one of the window.

Eli, you are right, it is in the Paint Event of the Subclass of Canvas that I created.

Taking it further, in the DrawInto Method I have to put the following:

[code] Dim d As Integer
me.graphics.ClearRect(0, 0, me.Width, me.Height)
me.graphics.ForeColor = App.DarkGray
me.graphics.FillRect(0,20,Me.width,Me.Height-20)
me.graphics.ForeColor = RGB(0,0,200)
me.graphics.FillRect(Left, top, me.Width, me.Height-24)
me.graphics.ForeColor=&cffffff

me.graphics.TextFont=“Helvetica”
me.graphics.Bold = True
me.graphics.TextUnit=FontUnits.Point
me.graphics.TextSize=16
d = me.graphics.Stringwidth(EntryText)
me.graphics.DrawString(EntryText, (Me.Width - d)/2,Top - 12)
d = me.graphics.StringWidth(“mm”)
me.graphics.DrawString(“mm”, (Me.Width - d)/2, Top - 2)
[/code]

Note in line 4 I again have to make the y axis 20 and the Height -20, or the graphics area goes to the top of the screen area, instead of the top of the canvas.

I realise I am doing something wrong, but I cannot for the life of me figure out what it is.

To fill a canvas with a color you have to write:
g.FillRect(0, 0, me.Width, me.Height) // The coordinates are local to the canvas, so the top left corner is really at 0, 0.

To test a canvas, put the following code in the Paint event:

g.ForeColor = RGB(255, 0, 0) g.DrawOval(0, 0, Me.Width, Me.Height)

The DrawInto method is for drawing into a picture’s graphics context (usually). As far as I understand your code above, I think you should move it into the Paint event (and replace Me.Graphics with g).

ClearRect is superfluous, since you fill the whole canvas anyway with some color on the next lines.

FillRect(Left, top, me.Width, me.Height-24) doesn’t make sense at all to me (left and top are properties of the window) - what are you trying to accomplish here?

You should put the following code at the end of the Paint event to prevent the Xojo framework from doing any drawing:

Return True

I can’t reproduce your results. Try creating a new, simple project with nothing but a control set of canvases. You will see that they draw correctly. Then work back to the code in your project and try to isolate where it goes wrong.

OK I will do that. But I have spent the last few minutes getting some screen shots of what I am talking about.

The first is from the IDE, you will see most of the canvases (the window is quite wide).

link text

Following is the Screenshot from the running program. I have pasted all the code that controls all this (I think).

link text

In the meantime I will start a simple project. All the canvases are in a Control Set, so maybe that is my problem.

Right, I created a new project with just one small canvas in it. It behaved as I want my other ones to.

So why should there be a difference. The canvas I have in my simple project is just that, not a subclass of a canvas.

Do you have some code that repositions the canvases somewhere in your project, like in the window open/resize events? Maybe they aren’t where you think they are after you show the window.

I think it is deprected to use me.graphics in context to a canvas. To replace me.graphics I would try this (bare in mind I have not tested it or proof-read it but you should get the idea):

Make a property for storing the graphics with the type of ‘picture’, in this example I will call it ‘PaintImage’.

PaintImage = new picture(me.width, me.height)
Dim d As Integer

  PaintImage.graphics.ClearRect(0, 0, me.Width, me.Height)
  PaintImage.graphics.ForeColor = App.DarkGray
  PsintImage.graphics.FillRect(0,20,Me.width,Me.Height-20)
  PaintImage.graphics.ForeColor = RGB(0,0,200)
  PaintImage.graphics.FillRect(Left, top, me.Width, me.Height-24)
  PaintImage.graphics.ForeColor=&cffffff
  
  PaintImage.graphics.TextFont="Helvetica"
  PaintImage.graphics.Bold = True
  PaintImage.graphics.TextUnit=FontUnits.Point
  PaintImage.graphics.TextSize=16
  d = PaintImage.graphics.Stringwidth(EntryText)
  PaintImage.graphics.DrawString(EntryText, (Me.Width - d)/2,Top - 12)
  d = PaintImage.graphics.StringWidth("mm")
  PaintImage.graphics.DrawString("mm", (Me.Width - d)/2, Top - 2)

And in the paint event:

g.DrawPicture PaintImage, 0, 0

Instead of:

[code] Dim d As Integer
me.graphics.ClearRect(0, 0, me.Width, me.Height)
me.graphics.ForeColor = App.DarkGray
me.graphics.FillRect(0,20,Me.width,Me.Height-20)
me.graphics.ForeColor = RGB(0,0,200)
me.graphics.FillRect(Left, top, me.Width, me.Height-24)
me.graphics.ForeColor=&cffffff

me.graphics.TextFont=“Helvetica”
me.graphics.Bold = True
me.graphics.TextUnit=FontUnits.Point
me.graphics.TextSize=16
d = me.graphics.Stringwidth(EntryText)
me.graphics.DrawString(EntryText, (Me.Width - d)/2,Top - 12)
d = me.graphics.StringWidth(“mm”)
me.graphics.DrawString(“mm”, (Me.Width - d)/2, Top - 2)[/code]

The canvas’ are being drawn correctly, just re-positioned incorrectly. I was assuming the same thing bill was, that the canvas X/Y is being re-positioned during an active event such as Window resize/open?

@oliver - the gauges should be updated when a change occurs, not on every paint event. The paint event occurs on window resize, focus/unfocus, mousedown/mouseup, and other instances which may be an overkill of drawing (CPU usage as well).
Me is only a reference to the self object, where in your example, the code is identical only you created a separate Picture class then loaded that object over the original (both are acceptable). I’ve seen the “depreciation” status and wondered about it since a canvas is a control which references a picture class, in turn which has a graphics class. The documentation says the ‘newly accepted’ method is to invoke a new picture class then call it’s graphics class. Are these redundantly the same in all essences?

Canvas can alias the Picture class…so
Canvas.graphics <> Picture.graphics ??? (possible depreciation because even though a canvas can alias a picture class its not directly a picture class? dunno)

Not even close to being the same. Also note that Canvas.graphics <> g as Graphics in the Canvas.Paint event.

I assume you’re referring to Canvas.Backdrop. It’s better to say, a canvas is a control that can use a Picture object as its source for graphics and automatically draw that image as needed.

[quote=80810:@Tim Hare]Not even close to being the same. Also note that Canvas.graphics <> g as Graphics in the Canvas.Paint event.

I assume you’re referring justto Canvas.Backdrop. It’s better to say, a canvas is a control that can use a Picture object as its source for graphics and automatically draw that image as needed.[/quote]

I see the difference now never really liked at it like that in the paint event (being active) as g as graphics, vs the static graphics class of the backdrop… Thanks tim just made the final link for me that I was missing (rather seeing incorrectly).

I can type. … phone just likes to spell and alter words at its own whims :-p

Thanks for all the replies. The thread is getting a little beyond my comprehension.

I miss-read Tim’s email by creating only one canvas. I have since created a control set of Canvases and they worked as expected.

I put the same code:

g.ForeColor = &c838383 g.FillRect(0,0,me.Width,me.Height)

into my Paint event and had the same problem as before. To overcome this I put the following code in the Paint Event:

[quote] g.ForeColor = &c838383
g.FillRect(0,20,me.Width,me.Height-20)
[/quote]

Which is, of course, the same as I had before. When I put this code into the Paint event of my simple canvas project, it shortened the canvas painted area by 20px. This, of course, suggests that I am moving the canvases prior to painting, but I cannot wee where this might be. I am not sure if this is possible or within the rules of this forum (if not, I apologise in advance), but the project is very small (284kb). I wonder if I could send it to someone to see what the problem is.

Bill, as far as I can be sure, I have no code that repositions the canvases.

I have created a Property PaintImage as suggestion by Oliver. I had no idea where to put the code he suggested, so I put it in the DrawInto method to the subclassed canvas. When I ran the When I ran the project, at first nothing happened (the canvases were not given the darkgray background), and when I entered some data, it didn’t display. So I am led to believe I have put the code in the wrong method?

I have managed to get the app running by “fudging” the y coordinates of the Paint and DrawInto methods, and have to continue that throughout the app. Until I can gain some more experience with Xojo, I think that will have to do. I am surprising myself at how quickly I am able to do things with Xojo, and what I am attempting here is a small, but for me complicated program. With trial and error, this forum, and reading the Language Reference and other docs, it is all starting to make sense.

Thanks to you all.

I’ll PM you my address so you can email it to me if you want me to take a look…

If you want to know for sure where the top of your canvas is at runtime, in your paint event you could put:

System.DebugLog "Canvas top: " + str(me.top)

Then to view that output, click on the right icon at the very bottom of the IDE, the one that looks kind of like a wifi signal. All System.DebugLog messages get printed there.

One other thing to check…did you lock the bottom of the canvas and unlock the top? That could result in it shifting upward when the window resizes without specifically moving them by code.

Hi Bill

No, I hadn’t. But I have since done that, and it made no difference.

System.DebugLog message saod that Canvas top was 0. So that is another pointer that I am inadvertently moving the canvases.

I have sent the Project to you.

Just to provide some closure for this, the OP had (unintentionally, I think) shadowed the Top property in his canvas subclass. That is, he had a subclass of Canvas, say it’s called subCanv. He had then added a property named Top to subCanv…it wasn’t being used so it was always zero. When the window opened, it looked for the Top value and got this zero instead of what he had designed in the IDE, so the canvas started at the top of the window instead of 20 down like he had intended.

Deleting or renaming the shadowed Top property fixed the issue.

I haven’t read it through completely, but there’s more info on why not to do this in the forum post “Shadowing Properties… Good or Bad?

Thanks for that explanation Bill. I was wondering quite why having the Top property in the subclass was a problem. When I created it I guess I had intended to use it, but didn’t. In fact I have deleted it from the subclass now.

Thanks again for all your help.