The deeepening mystery… Canvas!

In the current main window, I have set a bunch of Canvas and create a Control Set (except one whoi had code and I keep it to be able to test other features).

So, I had it working: six or seven Canvas had each one an unique image that came from data folders… I powered off the computer and goes to my “desktop”. After a reboot, I worked on that project (other parts), and run it to discover the icons are no more loaded / displayed. Fortunately, I’ve made a snapshot and, yes that worked some hour(s) ago !

This night, I wanted to check why, and this time I created a brand new project with the current Xojo. What was my surprise to discover… my code works (how can it not be, see it below).

I was thinking, it’s my working Xojo version who have the problem. I created the same example with Xojo 2021r2.1 and… it worked !

At this stage, my anger grows. I loaded my project (where it do not works anymore), add a window, addsome Canvas, set the code in a button and copy/paste the code: it works !

Back to my main window Open Event, comment everything excepted the relevant code who proved to be working elsewhere and… still not working.
I commented the code in App.Open (not needed for the test, check my main window, find code in Canvas1.Open: commented.
Clear the Caches, even power off…Power On, run Xojo, load the project, run: no image in my canvas !
My boot SSD have plenty room, no other running application.
WiFi was OFF.

No explanation from here !

Here’s the used code:

Dim f As New FolderItem("H Foster.png")

cGraphics(0).Backdrop = Picture.Open(f)
cGraphics(1).Backdrop = Picture.Open(f)

cTarzan.Backdrop = Picture.Open(f)

cCharacter(5).Backdrop = Picture.Open(f)

Ach ! I forgot: I add two more Canvas and set then as Control Set AFTER creation time (unlike the others: I add one Canvas, set it as a Control Set, and duplicate them 27 times…
This just in case it makes a difference.

BTW: the above code was running without result in wMain.Open, then I cut it from there and Paste it in a brand new button, run, click, same behavior: no icon on screen.

Who will resolve the mystery ?

PS: I can provide an example with the image, if needed, but the example works fine, thank you. :wink:

Here’s a screenshot of the working example:

Are you creating the canvases in API2 code (in which case are they being set as children of the windows?)

Or are you copying a control set canvas and pasting it nearby?

  • I wonder if the new canvases have a parent.
  • I wonder if they are ‘under’ an existing canvas
  • I wonder if they are children (inside) of another canvas.
  • I wonder if cGraphics(0).Backdrop is NIL after Picture.Open(f)
  • Maybe you need to .invalidate them?

.
.
.
.

To be honest, using canvases in this way is probably not the best plan.

Consider loading an array of pictures.
Once you know how many there are, you know how many you need to fit on screen.
Decide how many you want to display (columns and rows) , then use an x,y loop to .drawpicture each of them onto the window or a single canvas.


for x as integer = 0 to columns-1
for y as integer = 0 to rows-1
   if  y*columns + x <=  thearray.ubound then
         g.drawpicture thearray(y*columns + x), x* colwidth, y * rowheight, colwidth, rowheight, 0,0,thearray(y*columns + x).width, thearray(y*columns + x).height
//this forces all your pictures to be the same shape (colwdth * rowheight)
//you might consider adjusting for ratio
   end if
next
next

To know which picture has been clicked, calculate in reverse in Mousedown - something like this

dim thex as integer = x/colwidth
dim they = y/colwidth
clickedpicture  = they * columns + thex

I avoid names like “H Foster.png” to replace them with “H_Foster.png” I advise you to drag the file into your project. It will then be copied to the resources folder of your application. Your code will be easier to write and in the compiled version you will not have to verify its presence

Thank you JL,

Of course, you do not know because I do not explained. I load the image (icons for Canvas buttons) dynamically: the application knows nothing about them. So drag to the project is not relevant.

For the image name: not relevant too, because we are on macOS / 2025 and it loads fines → screen shot.

Hi Jeff,

I’ve created the first example with 2024r2, so they are API II. When I saw it works fine, I saved it and quit 2024r4.2 / Poser Off the computer… Power On, run only Xojo and create a ole API (not the API II) example.

No dependency with Parent or Child.

The only thing I do not check is if Graphics is Nil but since I used .Backgrop ?

Overlaping: without backdrop, your question is valid: but no, no overlaping (they are destined to be buttons).

Invalidate:
I used Refresh in 2021r2.1, but that changed nothing.

Actually, in the original project, I have two Controls (ListBox and TextArea for debug reports/testings) that are above some Canvas, but I apply no image to these Canvas (I created only 6 or 7 images, that is enough for now).

BTW: there is something I forgot: I fill one Backdrop in the IDE to know if the code try to display something in the Canvas. The image disappears when I click in the Load/Display the images…

Canvas as buttons.zip (22.6 KB)
23KB: the archive with the signature image.

Thank you, I will consider it (OK, I will implement it) a bit later, when I know I will have quiet hours to do that in good conditions (no boby comes / no phone / no…).

I found where the error is:

In each Canvas, I fill the babckground (light yellow) to be sure the objects are here and where they are. The code n paint is:

Sub Paint(index as Integer, g As Graphics, areas() As REALbasic.Rect) Handles Paint
  // Paint it Yellow, so I can see them…
  g.DrawingColor = cmy(0.0,0.0,0.2)
  g.FillRect 0,0, Me.Width,Me.Height
  g.DrawingColor = cmy(1.0,1.0,1.0)
  g.DrawRect 0,0, Me.Width,Me.Height
  End Sub

Nothing fancy.

Before giving up, I wanted to check if there is some code that access the .Backdrop property. So I opened the two “Canvas Set”, and in one, there was code. I commented it and run and my signatures are there.

Apparently, the .Graphics layer is above .Backdrop.

Mystery resolved !

Works fine for me in Xojo 2024 1.1 and 2021 R3

But your code
Dim f As New FolderItem("H Foster.png")
is once again a bad idea.

H Foster.png may be next to your compiled app, but it will not be next to your debugging app, and it will not be next to any app if it runs on a mac that has translocated the executable.

If Picture.Open(f) does not get a picture, it returns Nil.
Setting a backdrop to nil is valid, so you wont see any errors, and you are not testing whether Picture.Open has returned a picture.

I changed it to :


Dim f As folderitem = specialfolder.desktop.child("H Foster.png")

and it works fine for me when I place the image on the desktop.

In your unchanged code, add these lines to test that

dim d as picture = Picture.Open(f)
if d = nil then
  break
end if

That wasn’t in the sample project.

Emile je ne sais pas d’ou vient ton problème
mais pourquoi cherches tu des choses compliquées et non fiables alors que Xojo fait ça très bien et de façon sécurisé.
Regarde mes modifications.

Emile I don’t know how your problem comes from

But why are you looking for complicated and unreliable things when Xojo does it very well and securely.

Look at my changes.
Canvas as buttons.zip (25.4 KB)

I USE THAT TO BE SURE OF WHAT HAPPENS BECAUSE THERE IS A PROBLEM WITH THE CODE IN MY PROJECT.
This code is a way to know, not meant to be in an application.

Yes, I know it is a bad idea to use it in my application.

In my application, the data are in Application Data / com. and I load it from there.

In my application I check if the picture was loaded (as you wrote) into the temporary Picture, THEN set that temporary Picture to where I need it, in that case to Canvas1.Backdrop.

This project is not meant to be compiled in the next months, and because the example project is just an example project (to demonstrate something, not an example to follow) we do not care.

Yes, of course, I do not needed there, and in the project, not the example, this will be removed.

I think I will remove the FillRec soon and keep the DrawRect to keep a visual feedback during debug time to where the canvas are.

Le code utilisé provient de la documentation de Xojo.

Ceci dit, je ne vois pas ce que ton code change.

Tu as dragué une image dans le projet: pas conforme; les images sont à lire depuis un dossier situé dans Application Data.

à part ça, je ne vois pas/

Le projet partagé n’est qu’une démonstration d’un problème/non problème, pas un bout de code qui est dans une application.

Le 2021 dans le nom du projet fait référence à Xojo 2021r2.1 utilisé pour créer le projet.

I found the screenshot where i use the two ways to display an image (icon in this case):

1st Row (the characters appears in no order):
I drag the files to the project with optionkey down, then apply the icons to each Canvas.Backdrop. For testing and to have a better idea on what it looks like.

2nd Row: the icon characters are dynamically loaded from disk. The application do not know how many they are in thedata folder (I acess to this data folder using specialfolder.applicationdata.Child(myData_Name)
And you can see (if you know the characters) the Characters appears alphabetically sorted; from left to right:
Alley Oop, ■■■■ Tracy, Flash Gordon, Mandrake the Magician, Prince Valiant, Tarzan of the Apes and The Phantom.

My failing memory totally forgot that I add the yellow color in Graphics AFTER doing this snapshot.


This looks far more like buttons.

Emile

Cela change beaucoup de choses

Quand tu as un fichier sur n’importe quel support tu le glisses dans le projet.

A la compilation (ou en version debogue) il sera placé dans le dossier ressource.

Ensuite tu n’as plus a te soucier si le fichier est bien a un endroit précis.

Si tu distribues ton produit, tu n’auras pas a prevoir l’installation de ce fichier

et de gérer tes erreurs de programmation ou les audaces de l’utilisateur qui peut le detruire, le renommer …

Pour placer l’image sur l’interface il faut juste l’indiquer dans la propriété backdrop du controle.

Si tu veut le faire par une méthode tu vas ecrire:

cMatch(0).Backdrop = H_Foster

a la place de:

cMatch(0).Backdrop = Picture.Open(f)

It changes a lot of things

When you have a file on any medium you slide it into the project. Upon compilation (or in debogue version) it will be placed in the resource folder.

Then you no longer have to worry if the file is in a specific place.

If you distribute your product, you will not have to provide for the installation of this file and manage your programming errors or the audacity of the user who can destroy it, rename it…

To place the image on the interface you just have to indicate it in the background property of the control. If you want to do it by a method you will write:

cMatch(0). Backdrop = H_Foster

instead of:

cMatch(0). Background = Picture.Open(f)

Yes, @Emile_Schwarz , this is the best thing to do with files/images that the application will need. I have about 110 such files/images, they all sit in one folder and the IDE knows where they are. And as @J_Luc_Pellerin says, the IDE puts them in the app’s Resources folder, where at runtime the app knows where to find them. This really is a non-issue.

Emile has been writing this app (or something like it) for many years.
I’m pretty sure the images need to be be located in folders/ subfolders - a filing system for comics. In order that the data can change and grow over time, the images won’t be built into the app