| |||||||||||||||||||||||||||
|
| |||||||||||||||||||||||||||
Print This Article REALbasic University: Column 055
SimplePaint: Part IIIn our previous lesson, we got the basics of a paint program going. This week we must add some features to make it more complete.
Adding Color CapabilityBecause SimplePaint is for kids, we don't want confusing interface elements like floating palettes and toolbars. So how do we implement a way to change colors? Simple: we make the color palette part of the drawing! Little kids can't tell the different between a floating palette and something that's part of the drawing area anyway, so we'll just make a color palette that's part of the drawing area. That way they can't unintentionally move or close it. Save this image to your SimplePaint project folder: ![]() Now import it into your project by dragging it from the Finder to the project window. That should add an italicized item called "palette" to the list of objects in your project. (The italics tells you the object is imported but not embedded -- that is, it is linked to the original object on your hard drive. That means if you delete the original, your project won't compile.) Next, we need a canvas object within which to display the picture of our color palette. Drag a canvas -- that's the rectangle with the sky picture (not the sunset) -- from REALbasic's tool palette to paintWindow. Give the canvas these property settings: ![]() Good. Now we just need to add some code to make the color palette work -- actually change the color of our drawing tool. It's really very simple. Double-click on paletteCanvas to open its code editor. The Paint event is probably selected, but we want the mouseDown event. Switch to it and put in this line of code:
The part within parenthesis simply returns the color of the pixel that the mouse cursor is pointing at. Remember, me means the object that contains the code -- in this case, paletteCanvas. The graphics object of paletteCanvas contains whatever is drawn there (i.e. our palette graphic), and the pixel method returns the color of the pixel at the x, y coordinates passed. So all this line does is send the color clicked on to a method called changeColor. Now we just have to write that method! Go to the Edit menu and choose "New Method." Fill in the dialog like this: ![]() Here's the code for the method:
This routine is very simple. We store the new color in a temporary variable called tempC. We compare it to c (which is the current drawing color). If they don't match, there's been a color change. So we save the current color into oldC and make the current color match tempC (the new color). But sharp readers will realize this isn't going to compile: we have never defined oldC! Even sharper readers are wondering: what is oldC -- why are we saving the old color? The reason behind oldC is that in a moment we're going to add a cool (but ridiculously simple) feature: a way to toggle between the previously used color and the current color! For that feature to work, we must remember both the current color and the previous color: hence the need for oldC. So let's add the property: go to the Edit menu, choose "New Property," and give it this declaration: oldC as color. Now run the program. It should work great: if you click on a color in the color palette, it will begin drawing in that color. Since white is one of the colors on the palette, you can even erase now! ![]() But enough playing around. Let's add that feature I was just talking about. Go to paintWindow's keyDown event and put in this code:
As you can see, this swaps the current and previous colors if the user presses the space bar. Try it -- it's pretty cool! But here we notice a little problem: there's no way to know what the current color is without actually drawing a dot. Wouldn't it be better if there was some indicator of the current color?
Adding a Color IndicatorLet's add another canvas right under paletteCanvas. Give it these settings: ![]() So we know what this is, give it a label (drag on a staticText -- the tool palette item with the 'Aa'): ![]() Your paintWindow should look something like this: ![]() Now we just need to put in some code. Double-click on colorCanvas and put this code into the Paint event:
As you can probably figure out, this just fills the square with the current color. Then it draws a black border around the box. Why draw a border? (Hint: what would this canvas look like without a border if our current drawing color was white?) But if you run the program now, you'll see that the current drawing color never changes! What's up with that? Surely we've done everything correctly. The answer is that yes, we've done everything correctly, but we've forgotten one small detail. ColorCanvas is only drawn when the Paint event happens. Since the Paint event normally happens only after a dialog box or a window from another program covered up the control, our program, which is designed to run by itself, taking over the entire screen, will never automatically redraw itself! So the solution is we must force the control to redraw. We can easily do that with a colorCanvas.refresh command. So simply go back to our changeColor method and make it look like this:
Cool! Whenever our drawing color changes, colorCanvas is forced to repaint itself. Now when you run SimplePaint, the current color is reflected in the color indicator box.
Another ProblemYou may notice, however, that our program lets the user draw right over the controls we've added. That looks rather lame: ![]() I've got a solution, but I'd like to challenge you to come up with yours before next week. If you would like the complete REALbasic project file for this week's tutorial (including resources), you may download it here.
Next WeekWe fix the control-drawing problem of SimplePaint, and add more features.
NewsREALbasic Developer magazine is pleased to announce the immediate availability of Classified Advertising. Classifieds are text-only ads in various categories offering or seeking products and services. ![]() Classified Ads in REALbasic Developer are a fantastic value. Reach thousands of REALbasic users for as little as $12! Ads get even cheaper if you run the same ad in multiple issues. They're a great way to promote your business, website, product, plugin, "Made with REALbasic" software, recruit employees, etc. To order a Classified Ad, simply fill out the interactive online form which will tell you the exact cost of your ad, and pay via credit card. The deadline for advertising in the premiere issue of REALbasic Developer is May 22, 2002, so place your ad today!
LettersOur first letter this week comes from Charles, who ran into a problem with the Windows version of RBU Pyramid. Marc, Strange bug, Charles. I know very little about Windows compiling, so I'm not sure of the "correct" solution to this. On the Mac, the color of highlighting is controlled by settings in the Appearance control panel and REALbasic uses that setting -- perhaps there's an equivalent setting on the PC (but either RB's not using it or it's set to black). But in truth, RBU Pyramid was originally written with REALbasic 3 before RB had programmatic scroll support of editfields. The way to scroll then was to move the cursor by selecting some text and the editfield would automatically scroll so the selection was visible. Now that RB supports scrolling, there's no need for the help topics to be highlighted. You can either turn off highlighting with an editField1.selLength = 0 command, or use the editField1.scrollPosition method to scroll to the appropriate line. (The latter method is probably best, since you can scroll the help topic headline to the top of the editField. In fact, we do that in the bug fixing session of RBU 047.) Next, Ersin writes: I want to make a program that the user can give 2 numbers and the program calculate the sum and write the sum of the numbers. Hi Ersin! We've briefly covered things like this before, but to summarize, the problem you are dealing with is that editFields contain strings (text) and number variables (integers or doubles) contain only numbers. You cannot do math operations on text and you cannot do string operations on numbers. Fortunately, REALbasic provides methods for you to convert from one type to the other. The val() function turns a string into a number. The str() function does the reverse (number to string). So to add two editFields together and put the result in a third editField you'd do something like this:
The two val() functions turn the contents of editField1 and editField2 into numbers so you can add them. The addition is enclosed by an str() function which turns the result, which is a number, into a string, which is put into editField3. These first two methods, as you've probably figured out, do not work:
About the Column REALbasic University is a weekly instructional column on programming with REALbasic and is brought to you by REALbasic Developer, the magazine for REALbasic programmers. Each week we answer select reader questions, and we're always open to ideas for future columns. Send your questions to . (Keep your questions simple and specific. General queries like "How do I write my own web browser?" will be neglected.) Your question won't be answered immediately, but will be answered in a future column. (If you don't want your correspondence published, just be sure to indicate that when you write. Otherwise it's fair game.) About the Author See the REALbasic University Archives
REALbasic University contents ©2001-2004 by Marc Zeedar and REALbasic Developer. All Rights Reserved.
| |||||||||||||||||||||||||||