Page 1 of 2
Import Paint
Posted: Thu Oct 07, 2010 2:02 am
by Bantymom
I am trying to make the importing of images more automatic. Once I get ahold of the image, I think I can figure out how to set the name, size, and location automatically all by myself. However, I am having trouble with getting the image.
I did look it up in the dictionary:
Code: Select all
import paint from file "flowers.jpeg"
import audioClip from file "/sounds/temp/bugsounds.wav"
And I wrote mine based on those:
Code: Select all
import paint from file "/Macintosh HD/Users/rfcoach/Desktop/coloring pages/frog-LineDrawing.gif"
but I get the following error:
Code: Select all
button "ChalkDrawing": execution error at line 3 (import: can't open file, mask file or display) near "/Macintosh HD/Users/rfcoach/Desktop/coloring pages/frog-LineDrawing.gif", char 1
I thought that perhaps I needed to move the folder (with the file) into the revMedia folder in my applications folder, but that did not solve the problem.
I searched the forum as well and found the two following references:
http://forums.runrev.com/phpBB2/viewtop ... ort#p25150
On this page, the poster was able to get the "import paint" thing to work just fine:
I'm trying to build a stack that imports a little BW drawing on each page; and I can import it using "import paint from file "ATB2.jpg" in the script of a button.
And:
http://forums.runrev.com/phpBB2/viewtop ... ort#p25040
Update:
This works for loading and displaying the image:
import paint from file "P1D16C2.gif"
Then I found this!!!
http://forums.runrev.com/phpBB2/viewtop ... ort#p23276
jmburnod wrote:Hi Daniel
You can use this script
Code: Select all
on mouseup
ImportPicture
end mouseup
on ImportPicture
answer file "Choose an image"
if it = empty then
exit ImportPicture
end if
put it into TheFile
import paint from file TheFile
end ImportPicture
Best
Jean-Marc
It works great! But I don't know why or how. Specifically, I don't know:
1) how it knew which folder to go to
2) why it imported my image so easily here and I couldn't get it to work the other way.
I can get away with just using this, but I won't really learn anything that way, and so explanations will be accepted with great glee!
Thanks and Cheers,
Bantymom
Re: Import Paint
Posted: Thu Oct 07, 2010 2:12 am
by mwieder
Try putting a "put TheFile into msg" before your "import paint" line and see what rev thinks the file path really is. My guess is that it's slightly different from what you think it is.
Re: Import Paint
Posted: Thu Oct 07, 2010 4:26 am
by Bantymom
Yes! Thank you. That was it. It seems I don't need to specify my Hard Drive.
(my guess) /Macintosh HD/Users/rfcoach/Desktop/coloring pages/frog-LineDrawing.gif
(from msg) /Users/rfcoach/Desktop/coloring pages/frog-LineDrawing.gif
I am very happy to know what I really was on the right track and that I'm more inexperienced rather than crazy.
I am also happy that it didn't work the first time because I then went to search through the forum and found the nifty bit of script by Jean-Marc, which was where I was hoping I would be able to go with it.
*offers cookies*
Bantymom
Re: Import Paint
Posted: Thu Oct 07, 2010 7:55 am
by mwieder
Well, there's no better way to learn than by trying things that don't work.
You might also want to look at the defaultFolder property in the documentation, especially if you need to grab a bunch of images from the same folder.
Re: Import Paint
Posted: Fri Oct 08, 2010 3:12 am
by Bantymom
Thanks. The defaultFolder property was one of the many things I looked up as I tried to figure out how to be able to do this. It didn't work for the same reason, in that I had written the path incorrectly. For now, just being able to get access to my HD to find the pictures I want is enough for now, but using that property is high on my list of things to do once I get ready to load up everything to its fullest.
I am very happy with the Jean-Marc script. I have expanded on it to be able to easily get the three pictures I will need for the next level (as Tomas works through the levels faster than I can finish this stack, lol). The stack requires 3 versions of the same picture: a chalk drawing for the chalkboard, a line drawing that will be used for the student to color when they advance to the next level, and a colored version for when the student finishes the task but doesn't advance to the next level. I've attached a copy of the card (I made a separate stack for it as an example, the whole stack is too big right now). If you want to try it out, I've uploaded 3 different images in the next post since I can only upload 3 files at a time.
Below is the script. It gets the image for me, resizes it, positions it on the card, and locks it there before asking me for the name of the next one. If you look at the top of the file window when it opens for you to browse, you can see that it reminds you which kind of image you should be getting. I am new at this, so I am sure it is chunky. I don't mind that so much, because I can still understand it when I look at it again, but if someone were to suggest a way to remove some of the bloat, well then, I'll learn something new and become a little bit better at this because of that help. For example, I would have liked to do it as a repeat loop, but there are things that are different depending on which drawing it is. I also wondered if "case" would be better to use than the if-then statements.
Code: Select all
local tImage
on mouseUp
if existence (image "ChalkDrawing") then
delete image "ChalkDrawing"
end if
if existence (image "LineDrawing") then
delete image "LineDrawing"
end if
if existence (image "ColoredDrawing") then
delete image "ColoredDrawing"
end if
put 1 into tImage
ImportPicture
set name of last image to "ChalkDrawing"
set width of image "ChalkDrawing" to 250
set height of image "ChalkDrawing" to 500
set location of image "ChalkDrawing" to 140, 330
set layer of of image "ChalkDrawing" to 2
set the lockLocation of image "ChalkDrawing" to true
put 2 into tImage
ImportPicture
set name of last image to "LineDrawing"
set width of image "LineDrawing" to 250
set height of image "LineDrawing" to 500
set location of image "LineDrawing" to 400, 330
set layer of image "LineDrawing" to 3
set the lockLocation of image "LineDrawing" to true
put 3 into tImage
ImportPicture
set name of last image to "ColoredDrawing"
set width of image "ColoredDrawing" to 250
set height of image "ColoredDrawing" to 500
set location of image "ColoredDrawing" to 660, 330
set layer of image "ColoredDrawing" to 4
set the lockLocation of image "ColoredDrawing" to true
end mouseUp
on ImportPicture
if tImage = 1 then
answer file "Choose a ChalkDrawing"
end if
if tImage = 2 then
answer file "Choose a LineDrawing"
end if
if tImage = 3 then
answer file "Choose a ColoredDrawing"
end if
if it = empty then
exit ImportPicture
end if
put it into TheFile
import paint from file TheFile
end ImportPicture
Re: Import Paint
Posted: Fri Oct 08, 2010 3:14 am
by Bantymom
Three images if you want to try it out yourself:
Re: Import Paint
Posted: Fri Oct 08, 2010 11:31 am
by Klaus
Hi Bantymom,
you could use a repeat loop to delete the images:
Code: Select all
...
repeat for each item i in "ChalkDrawing,LineDrawing,ColoredDrawing"
if there is a img i then
delete img i
end if
end repeat
...
If someone CANCELs the import of an image, all the following scripting is amess and useless!
Know what I mean?
I would make a function from it like this:
Code: Select all
function importImage thenumber
switch thenumber
case 1
put "Choose a LineDrawing" into tDialog
break
case 2
put Choose a LineDrawing" into tDialog
break
case 3
put "Choose a ColoredDrawing" into tDialog
break
end switch
answer file tDialog
if it = empty then
return FALSE
end if
import paint from file it
return TRUE
end ImportImage
Then you can check if the user has actually imported an image and stop the script or whatever.
Code: Select all
..
put ImportImage(1) into tResult
if tResult = FALSE then
answer "I CANNOT WORK THIS WAY!"
exit mouseup
end if
...
Best
Klaus
Re: Import Paint
Posted: Sat Oct 09, 2010 2:47 am
by Bantymom
Oh my goodness!!! I see what you mean. I selected "Cancel" and was booted into the script. Yuck. Nope, that certainly wasn't part of the plan. I'm sure glad you brought that to my attention now.
I added a bit at the beginning (just before where I added your very lovely repeat to remove the existing images, so much tidier, thank you) to try to forestall that. It works quite nicely.
Code: Select all
on mouseUp
answer "Do you have three images ready to import?" with "no" or "yes"
if it = "no" then
exit to top
else
repeat for each item i in "ChalkDrawing,LineDrawing,ColoredDrawing"
if there is a img i then
delete img i
end if
end repeat
end if
(about "if there is a img i"... I like it much better than "existance." Other than the way it is formatted, is there a great difference between the two?)
I also tried putting in the function, but couldn't get it to work with the larger part of the script that renames, resizes, and places each of the three images. I haven't given up trying to understand it or use it, but it is going to take me time to figure it out, so for now, the other one is still there, except that I did use "switch" instead of "if/then".
Edit:
The trouble I was having with the Function was that I couldn't get it called (is that the right term?) in the middle of the sequence of events in the MouseUp Handler, where I wanted to intersperse the repeat of the common elements (ImportPicture) with the specifications of each different image. However, I did rewrite it to allow me to make more parts common (by using a variable for the name) and thus reduce the number of bits that had to be unique (location, and then locking it all up at the end). I used switch again and added an "exit to top" to just stop everything again if "Cancel" is chosen. Better?
Code: Select all
local tPicture
on mouseUp
... (as above through the "end if")
put "ChalkDrawing" into tPicture
importPicture --first case of the switch in importPicture
set location of image "ChalkDrawing" to 140, 330
set the lockLocation of image "ChalkDrawing" to true
put "LineDrawing" into tPicture
importPicture --second case of the switch in importPicture
set location of image "LineDrawing" to 400, 330
set the lockLocation of image "LineDrawing" to true
put "ColoredDrawing" into tPicture
importPicture --third case of the switch in importPicture
set location of image "ColoredDrawing" to 660, 330
set the lockLocation of image "ColoredDrawing" to true
end mouseUp
on importPicture
switch tPicture
case "ChalkDrawing"
answer file tPicture
break
case "LineDrawing"
answer file tPicture
break
case "ColoredDrawing"
answer file tPicture
break
end switch
if it = empty then
answer "You Didn't Choose An Image." & cr & "I Am Going to Exit Now." & cr & "I Need 3 Images To Make This Work"
exit to top
end if
put it into TheFile
import paint from file TheFile
set name of last image to tPicture
set width of image tPicture to 250
set height of image tPicture to 500
set layer of image tPicture to 2
end importPicture
It seems to be working so far, but I would really like to understand the Function thing. And is there any other way I can get myself into trouble?
Thanks,
Banty
*distributes cookies*
Re: Import Paint
Posted: Mon Oct 18, 2010 6:15 pm
by Klaus
Hi Bantymom,
here some thoughts and hints that might make your life easier
Your scripts show that you always use the same dimensions and locations for your three images.
Then you could use empty and static images that you just "fill" with the images the user selects.
Do this:
1. Create three (empty) images on your card, give them the right names, layers, dimensions and locations.
2. Then set their "lockloc" (check -> Inspector -> Size and Position -> lockloc/Lock size and position) for these images
3. Put this into your stackscripts, so all images will be "cleared" when the app starts:
Code: Select all
on preopenstack
## do this and that, whatever you need to :-)
repeat for each item i in "ChalkDrawing,LineDrawing,ColoredDrawing"
put empty into img i
## of card X if necessary
end repeat
end preopenstack
4. Now you have three ready-to-use images on your card and do not need to think about this anymore!
Next:
A function to import your images.
I would avoid a variable to hold the name of the current image-to-be-selected, just add a parameter to your function!
So you can simply pass the name of the current image and this script can even be in the card script!
Code: Select all
function importPicture tName_of_image
## In your case this will be one of ChalkDrawing, LineDrawing or ColoredDrawing
answer file "Please select an image for the" && tPicture
## Immediately store It into another variable, since IT changes whenever you least exspect it :-)
put it into tFile
## User cancel-led, we return FALSe
if tFile = empty then
answer "You Didn't Choose An Image." & cr & "I Am Going to Exit Now." & cr & "I Need 3 Images To Make This Work"
return FALSE
end if
## Now the script that put the complete image into our pre made image object:
put url("binfile:" & tFile) into img tName_of_image
return TRUE
end importPicture
Now you can call this function in your mouseup script:
Code: Select all
on mouseup
repeat for each item i in "ChalkDrawing,LineDrawing,ColoredDrawing"
put importPicture(i) into tSuccess
## Use cancel, so we are "out"
if tSuccess = FALSE then
exit to top
end if
end repeat
end mouseup
It is even not necessary to "clear" in the meantime the images since the "put url binfile..." will overwrite the existing images.
And as you see, no more setting the loc, layer and or dimensions, when you use my concept described above!
OK, this is a lenghty post, but also food for thought, hope you like it!
Best
Klaus
Re: Import Paint
Posted: Tue Oct 19, 2010 6:26 am
by Bantymom
Klaus,
Thank you for the wonderful suggestion. It sounds very promising. Very sneaky of you too, making me have to actually go learn about the difference between handlers and functions. I have been afraid of functions and so have been avoiding them, but now, well, *sigh* it looks like I am going to have to get brave and just sit down and do it!
I am going to have to learn about the empty Image holder Control thing too. Am I to understand that once one of these things has been set up, any image imported into it will simply fill the space available? With the commands to set the size and position each time, I haven't had to worry about making each and every image perfectly sized before uploading them, which has been nice.
I have a little question... Will this still work without running the stack on the internet? I have been using StackRunner to keep everything self-contained. You have no idea just how much trouble a 2nd-grader can get into once he or she opens Safari.
Oh boy! I'm so excited now! I like it so much better when things are neat and tidy.
Cheers,
Bantymom
Re: Import Paint
Posted: Tue Oct 19, 2010 11:17 am
by Klaus
Hi Bantymom,
glad you like my "clean" approach!
And yes I also like it when things are neat and tidy!
And yes, the images are "re-filled" everytime with the new content (= the new images).
Think of an image just like a field that can be filled with content!
What exactly do you mean by "Will this still work without running the stack on the internet?"
This should work whenever the stack is opened, no matter how it is opened.
Best
Klaus
Re: Import Paint
Posted: Sat Oct 23, 2010 6:00 am
by Bantymom
Using the empty image Control place holder is working like a charm! I love it! However, while working on the function, I run into a bit of confusion.
Code: Select all
function importPicture tName_of_image
## In your case this will be one of ChalkDrawing, LineDrawing or ColoredDrawing
answer file "Please select an image for the" && tPicture
## Immediately store It into another variable, since IT changes whenever you least exspect it :-)
put it into tFile
## User cancel-led, we return FALSe
if tFile = empty then
answer "You Didn't Choose Your Image." & cr & "I Am Going to Exit Before I Crash." & cr & "I Need 3 Images To Make This Work"
return FALSE
end if
## Now the script that put the complete image into our pre made image object:
put url("binfile:" & tFile) into img tName_of_image
return TRUE
end importPicture
In my plain handler, the procedure continued right along because it went along in the switch thingy, which was very nice for me as it asked for each one automatically
I am not sure if the function works the same way or if I need to make it separate for each of the three images or not. I would also really like to understand the advantage of functions over handlers, or should that be a separate topic?
Edit:
I kept working and working on it, but I kept getting tangled in some parts. That struggle did, however, lead to a script that requires no other handler or function to be called at all. Just look how much shorter it is! Not shorter than yours, true, but shorter than the one I wrote first.
Code: Select all
on mouseUp
answer "Do you have three images ready to import?" with "no" or "yes"
if it = "no" then
exit to top
else
repeat for each item tPicture in "ChalkDrawing,LineDrawing,ColoredDrawing"
put empty into img tPicture
answer file tPicture
if it = empty then
answer "Ooops. You dropped one. I'm aborting the mission." & cr & "You need to do it again or the game will crash."
exit to top
end if
put it into tFile
put url("binfile:" & tFile) into img tPicture
end repeat
end if
end mouseUp
I am SO happy! But I will keep working to understand functions.
Second edit: lol, my next post will equal my age.
Re: Import Paint
Posted: Sat Oct 23, 2010 11:39 am
by Klaus
Hi Bantymom,
the main difference between function and handlers is that functions are supposed to return a value (not necessarily),
but handlers don't (necessarily!).
Your handlers look good and effective and since everything is working fine for you there is no need for you to change
a single line
The main reasons why we tend to use extra functions and handlers are: effectiveness, re-use by all other objects and
easy maintenance!
If you "outsource" handlers and functions, they are easier to maintain: ONE (complex) script VS x different (smaller) scripts!
Know what I mean?
Best
Klaus
Re: Import Paint
Posted: Sat Oct 23, 2010 8:56 pm
by Bantymom
Thank you very much. What you have taught me here about the empty image container has been amazing! Also, using "repeat" for a string of different situations instead of using switch is liberating. I've seen it used before, but until I saw it with a string of references I recognized, I wasn't sure what was happening. Because of just those two things, I was able to reduce what used to be 52 lines to 14!
But, let me see if I understand this correctly.
Handler: when it is told "run" (is sent a message or is called upon by another handler), it performs a series of tasks, which may or may not include supplying the user with an answer of some kind ("answer tResult" or some such thing).
Function: when it is called upon to "run," it does it's work, but is also monitoring itself and what it is processing and in addition to getting its work done, embodies within itself information on whether something is there or not, something is true or not, or whether something happened or did not. That information or result can be reported to the user or used for something else if needed, without having to write other bits of code to get at it.
So, as soon as I find myself writing something into a handler that reports something to me or that is testing whether something happened or not, I should consider a function instead of a handler. Yes?
When you say that the reason we use extra functions and handlers is to to allow other objects to use the same thing and to more easily maintain the script, are you are referring to custom handlers, those things I think of as little macros (geez, I'm old) that I can put somewhere that is easy to get to and then refer other objects or handlers to them instead of rewriting the same script over and over? For example, there are 20 buttons on my game card that the student can click to get a word to solve. The script for each button is simply "clickButton." In the card script for that card is the handler "on clickButton" in which I wrote what was to happen. That way, as I tinkered with it, I only had to make the changes there, once, instead of having to make the change 20 times. That is what you meant? Is that also what you mean by "outsourcing" handlers and functions?
After I import those images, I use them in various places in the game. I am going to rewrite those bits to use the empty image container as well so I can eliminate all of the formatting and placing bits of code. More on that later. *imagines her bloated code shrinking little by little*
Now, here is a situation where I will be able to apply both the empty image container concept and the custom (outsourced?) handler to solve a problem that has recently arisen:
Tomas sometimes messes up the painting of the picture, making it all one color. Command-Z does not work on painting tools (I looked it up), so even though he knows that trick, it does him no good in that situation. I want him to be able to press a button and have a second chance at it. This means that the original picture has to be found, copied, formatted into place again, and the paint buttons reset. These things happen at different places in the stack, and setting the picture into place the first time involves all of that formatting you saw before. But now I can set up an empty image container on the Painting Card for the original image to be copied into, no formatting required! Then, instead of copying that same script and Bernd's painting script to the new "Try-The-Painting-Again" button, I will make those two different scripts into custom handlers which can be called upon at the beginning of the game for the set up, and can be called upon again if the picture needs to be reset.
*does the happy dance*
PS: To answer a previous question, I thought that maybe with the new script you had suggested, I would have to host my game on the internet because in the line that puts the image into the empty image container, I saw the word "url," which I have always associated with the internet. Now I know that "url" can also refer to the place the image resides on my computer. When I looked up "binfile" it was cleared up.
Re: Import Paint
Posted: Sat Oct 23, 2010 9:53 pm
by mwieder
But, let me see if I understand this correctly.
You got it.
Is that also what you mean by "outsourcing" handlers and functions?
You also got that one pretty much correct, although I think the "outsourcing" term may have lost a bit in the translation from the German. So in addition to what you already figured out, you can place your code somewhere low enough in the message path for all the objects that need it can get to it. That way you only have to change code in one place.
In your example you placed the "on ClickButton" code in the card script, and that way all the buttons on the card have access to it. If you needed to get to the ClickButton handler from other cards as well, you'd probably move the "on ClickButton" handler to the stack script rather than replicate it on other cards.