Explore MIT App Inventor - Drawing Canvas http://dev-explore.appinventor.mit.edu/tutorial-type/drawing-canvas en PaintPot (Part 2) for App Inventor 2 http://dev-explore.appinventor.mit.edu/ai2/paintpot-part2 <div class="field field-name-body field-type-text-with-summary field-label-hidden view-mode-rss"><div class="field-items"><div class="field-item even" property="content:encoded"><p>This tutorial has two parts: <a href="/ai2/paintpot-part1">Part 1</a> | <a href="/ai2/paintpot-part2">Part 2</a> </p> <p>Part 2 extends <a href="/ai2/paintpot-part1">Part 1</a> of the tutorial to create both large and small dots, as a demonstration of how to use <em>global variables</em>.</p> <h4 class="ai-header">Starting</h4> <p>Make sure you've completed the <a href="/ai2/setup">Set Up</a> process and you have your completed project from <a href="/ai2/paintpot-part1">PaintPot Part 1</a> loaded.</p> <p>Start where you left off at the end of Part 1, with the project open in App Inventor. Use the <strong>Save As</strong> button to make a copy of <span style="color:green;">PaintPot</span> so you can work on the new version without affecting the original version. Name the copy "PaintPotV2" (with no spaces). After saving a copy, you should see <span style="color:green;">PaintPotV2</span> in the Designer.</p> <h4 class="ai-header">Creating variables</h4> <p>The size of the dots drawn on the canvas is determined in the <span class="basicblock">when DrawingCanvas.Touched</span> event handler where <span class="callblock-ai2">call Drawing.DrawCircle</span> is called with <strong style="color:green;">r</strong>, the radius of the circle, equal to 5. To change the thickness, all we need to do is use different values for <strong style="color:green;">r</strong>. Use <strong style="color:green;">r</strong> = 2 for small dots and <strong style="color:green;">r</strong> = 8 for large dots.</p> <p>Start by creating names for these values:</p> <ol><li>Open the Blocks Editor if it isn't already open and connect the phone. Your phone should show the buttons and the canvas you built previously.</li> <li>In the Blocks Editor, in the Built-In column, open the Variables drawer. Drag out a <span class="variableblock">initialize global name to</span> block. Change the text that reads "name" to read "small". A yellow warning exclamation mark might appear on the block. If you mouse over this you'll see a warning message explaining that the block has an empty socket.</li> <li>You need to fill in the socket with a number block that specifies the value for "small" -- use 2 as the value. To create the number block, type the number 2. A menu will appear, showing you all the possible blocks that include "2" in their name. Click on the first one, which is the <span class="mathblock">number 2</span> itself, and a number block with the value 2 should appear. Plug that in to the <span class="variable block">initialize global small to</span> block. The yellow warning mark will disappear, because the empty socket has been filled. (The second value listed in the menu is the math block <span class="mathblock">atan2</span> which you won't use here.)</li> </ol><p>Here are the steps in the sequence:</p> <ol><li><img src="/sites/all/files/ai2tutorials/paintPot2/var1.png" /></li> <li><img src="/sites/all/files/ai2tutorials/paintPot2/var2.png" /></li> <li><img src="/sites/all/files/ai2tutorials/paintPot2/var3.png" /></li> <li><img src="/sites/all/files/ai2tutorials/paintPot2/var4.png" /></li> <li><img src="/sites/all/files/ai2tutorials/paintPot2/var5.png" /></li> </ol><p>You've now defined a global variable named <span class="variableblock">small</span> whose value is the number 2.<br /> Similar to <span class="setblock">small</span>, define a global variable <span class="variableblock">big</span>, whose value is 8.<br /> Finally, define a global variable <span class="variableblock">dotsize</span> and give it an initial value of 2.</p> <pre class="ai-box">You might wonder whether it would be better programming style to make the initial value of <span style="color:black;">dotsize</span> be the value of <span style="color:black;">small</span> rather than 2. That would be true, except for a subtle programming point: Doing that would be relying on the assumption that <span style="color:black;">small</span> will already have a value at the point in time when <span style="color:black;">dotsize</span> is assigned its value. In App Inventor, you can't make assumptions about the order in which different <span class="setblock" style="color:black;">def</span> blocks will be processed. In general, of course, you really <em>would</em> like to specify the order in which variables are assigned. You can do this by assigning all values when the application is initialized, using the Screen initialize event. The <a href="http://appinventor.mit.edu/explore/content/quizme.html">Quiz Me</a> tutorial gives an example of initialization.</pre><h4 class="ai-header">Using variables</h4> <p>Now go back to the touch event handler you set up in Part 1 and change the <span class="callblock-ai2">call to DrawCircle</span> block so that it uses the value of <span style="color:green;">dotsize</span> rather than always using 5.</p> <p>In the Blocks Editor, switch to the My Blocks column, and open the Variables drawer. Pull out a get block and click on the dropdown. You should see three new variables in the dropdown: small, big, and dotsize</p> <p>These blocks were automatically created and put in the dropdown of <span class="variableblock">get</span> and <span class="variableblock">set</span> variable blocks, similarly to the way that x and y were created in the dropdown when you defined the <span class="eventblock">when DrawingCanvas.Touched</span> event handler in the part 1 of this tutorial. "Global" means "global variable", in contrast to the event-handler arguments, which are considered "local variables". The difference is that the argument values are accessible only within the body of the event handler, while global variables are accessible throughout the entire program.</p> <ul><li>Go to the <span class="eventblock">when MyCanvas.Touched</span> event handler and replace the number 5 block in <span class="callblock-ai2">call DrawCircle</span> with the <span class="variableblock">get dotsize</span> block from the Variables drawer.</li> </ul><h4 class="ai-header">Changing the values of variables</h4> <p>Now set up a way to change dotsize to be small (2) or big (8). Do this with buttons.</p> <ol><li>In the Designer, drag a <strong>HorizontalArrangement</strong> component into the Viewer pane below the <span style="color:green;">DrawingCanvas</span> component. Name the component "BottomButtons".</li> <li>Drag the existing <span style="color:green;">ButtonWipe</span> into <span style="color:green;">BottomButtons</span>.</li> <li>Drag two more button components from the Palette into <span style="color:green;">BottomButtons</span>, placing them next to <span style="color:green;">ButtonWipe</span>.</li> <li>Name the buttons "ButtonBig" and "ButtonSmall", and set their <strong style="color:green;">Text</strong> to read "Big dots" and "Small dots", respectively.</li> <li>In the Blocks Editor under My Blocks, create a <span class="eventblock">when ... Clicked</span> event handler for <span style="color:green;">ButtonSmall</span> that changes <span style="color:green;">dotsize</span> to be the value of <span style="color:green;">small</span>. To change <span style="color:green;">dotsize</span> use the <span class="variableblock">set global dotsize to</span> block from the MyDefinitions drawer and plug in the <span class="variableblock">global small</span> block.</li> <li>Make a similar event handler for <span style="color:green;">ButtonBig</span>.</li> </ol><p>The two click event handlers should look like this:</p> <p><img src="/sites/all/files/ai2tutorials/paintPot2/PaintPotDotsClick.png" /></p> <p>You're done! You can draw in <span style="color:green;">PaintPot</span> and use the new buttons to draw either big dots or small dots. Notice that dragging your finger still produces a thin line. That's because the changes we just made don't affect how <span class="callblock-ai2">DrawLine</span> is called.</p> <p>Here's the finished program in the Designer:</p> <p><img src="/sites/all/files/ai2tutorials/paintPot2/PaintPotAllDesigner.png" /></p> <p>and in the Blocks Editor:</p> <p><img src="/sites/all/files/ai2tutorials/paintPot2/PaintPotAllBlocks.png" /></p> <pre class="ai-box">A bug for you to work on: The program you just built has a slight bug. If you start drawing before pressing any of the paint buttons, the paint color will be black; however, after you choose a color, there's no way to get back to black. Think about how you could fix that.</pre><h4 class="ai-header">Review</h4> <p>You create global variables by using <span class="variableblock">def</span> blocks from the Variables drawer.</p> <p>For each global variable you define, App Inventor automatically supplies a <span class="variableblock">global</span> block that gives the value of the variable, and a <span class="variableblock">set global ... to</span> block for changing the value of the variable. These blocks can be found in the Variables drawer.</p> <h4 class="ai-header">Scan the Sample App to your Phone</h4> <p>Scan the following barcode onto your phone to install and run the sample app. </p><p><img src="/sites/all/files/ai2tutorials/paintPot2/PaintPot2Barcode.png" /></p> <p>Or <a href="/sites/all/files/ai2tutorials/paintPot2/PaintPot2.apk">download the apk</a></p> <h4 class="ai-header">Download Source Code</h4> <p>If you'd like to work with this sample in App Inventor, download the <a href="/sites/all/files/ai2tutorials/paintPot2/PaintPot2.aia">source code</a> to your computer, then open App Inventor, go to the My Projects page, and choose <b>More Actions | Upload Source</b>.</p> <pre class="ai-box">Done with <span style="color:black;">PaintPot</span>? Return to the other tutorials <a href="/ai2/tutorials">here</a>.</pre></div></div></div><section class="field field-name-field-version field-type-taxonomy-term-reference field-label-above view-mode-rss clearfix"> <h2 class="field-label">Tutorial Version:&nbsp;</h2> <ul class="field-items"> <li class="field-item even"> <a href="/tutorial-version/app-inventor-2" typeof="skos:Concept" property="rdfs:label skos:prefLabel" datatype="">App Inventor 2</a> </li> </ul> </section> <section class="field field-name-field-tutorial-difficulty field-type-taxonomy-term-reference field-label-above view-mode-rss clearfix"> <h2 class="field-label">Tutorial Difficulty:&nbsp;</h2> <ul class="field-items"> <li class="field-item even"> <a href="/tutorial-difficulty/basic" typeof="skos:Concept" property="rdfs:label skos:prefLabel" datatype="">Basic</a> </li> </ul> </section> <section class="field field-name-field-tutorial-type field-type-taxonomy-term-reference field-label-above view-mode-rss clearfix"> <h2 class="field-label">Tutorial Type:&nbsp;</h2> <ul class="field-items"> <li class="field-item even"> <a href="/tutorial-type/drawing-canvas" typeof="skos:Concept" property="rdfs:label skos:prefLabel" datatype="">Drawing Canvas</a> </li> </ul> </section> Tue, 16 Jul 2013 14:33:50 +0000 joanie 364 at http://dev-explore.appinventor.mit.edu http://dev-explore.appinventor.mit.edu/ai2/paintpot-part2#comments PaintPot (Part 1) for App Inventor 2 http://dev-explore.appinventor.mit.edu/ai2/paintpot-part1 <div class="field field-name-body field-type-text-with-summary field-label-hidden view-mode-rss"><div class="field-items"><div class="field-item even" property="content:encoded"><p>This tutorial has two parts: <a href="/ai2/paintpot-part1">Part 1</a> | <a href="/ai2/paintpot-part2">Part 2</a> </p> <p>This tutorial introduces the <strong>Canvas</strong> component for creating simple two-dimensional graphics. You'll build an app that lets you draw on the phone screen in different colors.</p> <pre class="ai-box"><strong>Historical note</strong>: PaintPot was one of the first programs developed to demonstrate the potential of personal computers, as far back as the 1970s.</pre><p><a href="http://cs.usfca.edu/~wolber/appinventor/bookSplits/ch2PaintPot.pdf">Download Book Chapter PDF</a></p> <h4>What you're building</h4> <p><img style="float:right;margin:5px;" src="/sites/all/files/ai2tutorials/paintPot1/PaintPotPart1PhoneImage.png" /></p> <p>With the <span style="font-style:italic;">PaintPot</span> app, you can:</p> <ul><li>Dip your finger into a virtual paint pot to draw in that color.</li> <li>Drag your finger along the screen to draw a line.</li> <li>Tap the screen to make dots.</li> <li>Use the button at the bottom to wipe the screen clean.</li> <li>Include an image as a drawing background.</li> </ul><p><span style="font-style:italic;"> <p>This tutorial assumes that you have completed the <a href="/ai2/hellopurr">HelloPurr</a> tutorial. This tutorial introduces the following App Inventor concepts:</p> <ul><li>The <strong>Canvas</strong> component for drawing.</li> <li>Controlling screen layout with <strong>Arrangement</strong> components.</li> <li>Event handlers that take arguments.</li> <li>Variables.</li> </ul><h4 class="ai-header">Before starting</h4> <p>Make sure your computer and your phone are set up to use App Inventor. Start a new project in the Designer window, and name it <span style="font-style:italic;">"PaintPot"</span>. Open the Blocks Editor, click <strong>Connect to Phone</strong>, and make sure the phone has started the App Inventor app.</p> <h4 class="ai-header">Screen title</h4> <p>To get started, go to the Properties panel on the right of the Designer and change the screen <strong>Title</strong> to "PaintPot". You should see this change on phone, with the new title showing in the title bar.</p> <p>There are three names in App Inventor, and it's easy to confuse them:</p> <ol><li>The name you choose for your project as you work on it (in this case, <span style="font-style:italic;">PaintPot</span>). This will also be the name of the application if you package it for the phone.</li> <li>The name "Screen1", which is the name of the <strong>Screen</strong> component. You'll see it listed in the Components panel in the Designer. You can't change the name of the first Screen component in the current version of App Inventor but you can create additional screens with names of anything you should choose.</li> <li>The <strong>Title</strong> property of the screen, which is what you'll see in the phone's title bar. Title is a property of the <strong>Screen</strong> component. The Title starts out being "Screen1", which is what you used in <span style="font-style:italic;">HelloPurr</span>. However, you can change it, as you're doing for <span style="font-style:italic;">PaintPot</span>. To reiterate, the name and the title of Screen1 are initially the same, but you can change the title if you want.</li> </ol><h4 class="ai-header">Set up the Components</h4> <p>You'll use these components to make <span style="font-style:italic;">PaintPot</span>:</p> <ul><li>Three <strong>Buttons</strong> for selecting <strong style="color:red">red</strong>, <strong style="color:blue">blue</strong>, or <strong style="color:green">green</strong> paint, and another button for wiping the drawing.</li> <li>A <strong>Canvas</strong>, the drawing surface. This canvas has a <strong>BackgroundImage</strong>, which is <a href="/sites/all/files/ai2tutorials/helloPurr/kitty.png">this kitty</a> from the <span style="font-style:italic;">HelloPurr</span> tutorial. You can also draw on a blank canvas. That's just a canvas without a background image.</li> <li>There's also a component you don't see: you use a <strong>HorizontalArrangement</strong> to make the three color buttons line up.</li> </ul><p>That makes five components in all. Let's get them and build the app.</p> <h4 class="ai-header">Color Buttons</h4> <ul><li>Drag a <strong>Button</strong> component onto the Viewer and change the button's <strong>Text</strong> attribute to "Red" and make its <strong>BackgroundColor</strong> red.</li> <li>Click on <span style="font-style:italic;">Button1</span> in the components list in the Viewer to highlight it (it might already be highlighted) and use the <strong>Rename...</strong> button to change its name from "Button1" to "ButtonRed".</li> <li>Similarly, make two more buttons for blue and green, named "ButtonBlue" and "ButtonGreen", placing them vertically under the red button.</li> </ul><p>Here's how this should look in the designer, with the button names appearing in the list of project components. In this project, you're changing the names of the components rather than leaving them as the default names as you did with <span style="font-style:italic;">HelloPurr</span>. Using meaningful names makes your projects more readable to yourself and others.</p> <p><img src="/sites/all/files/ai2tutorials/paintPot1/PaintPotThreeButtonsVertically.png" /></p> <p>You should also see the three buttons on the phone screen.</p> <h4 class="ai-header">Layout with Screen Arrangement</h4> <p>You should now have three buttons, one above the other. The next step is to make them line up horizontally. You do this using a <strong>HorizontalArrangement</strong> component.</p> <ol><li>From the Palette's Screen Arrangement category, drag out a <strong>HorizontalArrangement</strong> component and place it under the buttons. Change the name of this component from "HorizontalArrangement1" to "ThreeButtons".</li> <li>In the Properties panel, change the <strong>Width</strong> of <span style="font-style:italic;">ThreeButtons</span> to "Fill Parent..." so that it fills the entire width of the screen.</li> <li>Move the three buttons side by side into the <strong>HorizontalArrangement</strong> component. <strong>Hint</strong>: You'll see a blue vertical line that shows where the piece you're dragging will go.</li> </ol><p>If you look in the list of project components, you'll see the three buttons indented under the <span style="font-style:italic;">ThreeButtons</span> to show that they are now its subcomponents. Notice that all the components are indented under <span style="font-style:italic;">Screen1</span>.</p> <p><img src="/sites/all/files/ai2tutorials/paintPot1/PaintPotThreeButtonsHoriz.png" /></p> <p>You should also see your three buttons line up in a row on the phone screen, although things might not look exactly as on the Designer. For example, the Arrangement's outline shows in the Designer but not on the phone.</p> <p>In general, you use Screen Arrangement to create simple vertical or horizontal layouts. You can create more complex layouts by nesting Screen Arrangement components. There is also a <strong>TableArrangement</strong> component (not covered in this tutorial).</p> <h4 class="ai-header">Canvas and wipe button</h4> <p>The final two components are the canvas and the wipe button.</p> <ol><li>From the Palette's Basic category drag a <strong>Canvas</strong> component onto the Viewer. Change its name to "DrawingCanvas". Set its <strong>Width</strong> to "Fill Parent" and set its <strong>Height</strong> to 300 pixels.</li> <li>Add a Background Image to the <strong>Canvas</strong>. Click on the field containing "None..." next to <strong>BackgroundImage</strong> in the canvas's Properties panel. You can use the same kitty.png file, if you still have it on your desktop from an earlier tutorial. Or you can use another image.<br /><pre class="ai-box">You can use any image you like, but you'll get the best results if the size of the image (in pixels) is close to the size at which you'll be showing it on the phone. Also, large images will take a long time to load, and might exceed the memory capacity of the phone allocates for applications.</pre></li> <li>From the Palette, drag the final button onto the screen, placing it under the canvas. Change its <strong>id</strong> to "ButtonWipe" and change its <strong>Text</strong> attribute to "Wipe".</li> </ol><p>You've now completed the steps to set the appearance of your app. Here's how this should look in the Designer. Next, you'll define how the components behave.</p> <p><img src="/sites/all/files/ai2tutorials/paintPot1/PaintPotDesigner.png" /></p> <h4 class="ai-header">Add behaviors to the components</h4> <p>Click the Blocks button to switch to the Blocks Editor. First you will set up the buttons that change the paint color. Later you will add blocks to decide what happens when someone touches or drags the screen.</p> <h4 class="ai-header">Add button event handlers</h4> <p>In the Blocks Editor:</p> <ol><li>Open the drawer for <span style="font-style:italic;">ButtonRed</span> and drag out the <span class="basicblock">when ButtonRed.Click </span> block.</li> <li>Open the <span style="font-style:italic;">DrawingCanvas</span> drawer. Drag out the <span class="setblock">set DrawingCanvas.PaintColor to </span> block (remember that the set block of components is a <a href="/concepts/dropdowns">dropdown</a> so PaintColor is a selection in the dropdown) and place it in the <span class="basicblock">do</span> section of <span class="basicblock">when ButtonRed.Click </span>.<br /><img src="/sites/all/files/ai2tutorials/paintPot1/canvasdropdown.gif" /></li> <li>Open the Colors drawer and drag out the block for the color Red and put it into <span class="componentsetblock">set DrawingCanvas.PaintColor to </span>. (Clicking on a color block after it's been placed will display a table of colors that you can select from.)</li> <li>Repeat steps 2-4 for the blue and green buttons.</li> <li>The final button to set up is the Wipe button. Make a click event handler for <span style="font-style:italic;">ButtonWipe</span> by dragging <span class="eventblock">when ButtonWipe.Click </span> from the <span style="font-style:italic;">ButtonWipe</span> drawer. From the <span style="font-style:italic;">DrawingCanvas</span> drawer, drag <span class="callblock">call DrawingCanvas.Clear </span> and place it in the <span class="eventblock">do</span> area of the <span class="eventblock">when ButtonWipe.Click</span> block.</li> </ol><p>The blocks for the buttons should look like this:</p> <p><img src="/sites/all/files/ai2tutorials/paintPot1/buttonsclick.png" /></p> <h4 class="ai-header">Add Touch-event Handlers</h4> <p>Now for the next step: drawing on the <strong>Canvas</strong>. You'll arrange things so that when you touch the canvas, you get a dot at the spot where you touch. If you drag your finger slowly along the canvas, it draws a line.</p> <ul><li>In the Blocks Editor, open the drawer for the canvas and drag the <span class="eventblock">when DrawingCanvas.Touched</span> block to the workspace. As soon as you drag the block out, you may notice three argument names located at the top of the block <strong>x</strong>, <strong>y</strong>, and <strong>touchedSprite</strong>. These arguments are also known as local variables and can get accessed by using the <span class="getblock">get</span> or <span class="setblock">set</span> block found in the Variables drawer.</li> </ul><p>You've already seen button click events. Clicks are simple, because there's nothing to know about the click other than that it happened. Other event handlers such as <span class="eventblock">when ... Touched</span> need information about the event. In App Inventor, this information is expressed as the value of arguments associated with the event handler. For the <span class="eventblock">when ... Touched</span> event, the first two arguments stand for the x and y coordinates of where the touch happened. We'll save <strong>touchedSprite</strong> for a later tutorial.</p> <ul><li>For this touch event, make the canvas draw a small circle at the point with coordinates (x, y). Drag out a <span class="callblock">call DrawingCanvas.DrawCircle</span> command from the canvas drawer and place it in the <span class="eventblock">do</span> section of <span class="eventblock">when DrawingCanvas.Touched</span>.</li> </ul><p>On the right side of the <span class="callblock">call DrawingCanvas.DrawCircle</span> block are three sockets where you must specify values for the x and y coordinates where the circle should be drawn, and <strong>r</strong>, which is the radius of the circle. For <strong>x</strong> and <strong>y</strong>, you'll use values of the arguments that were supplied to the Touched handler:</p> <ol><li>Open the Variables drawer. Find the <span class="getblock">get</span> block.</li> <li>Drag out two <span class="getblock">get</span> blocks and plug them into the corresponding sockets in the <span class="eventblock">when DrawingCanvas.Touched</span> block. Click on the dropdown to select <strong>x</strong> and <strong>y</strong> in the corresponding block.</li> <li>You'll also need to specify the radius of the circle to draw. Five (pixels) is a good value for this app. Click in a blank area of the screen and type the number 5 followed by return to create a number block with a value of 5. Typing on the blank area of the screen is called <a href="/concepts/typeblocking">typeblocking</a> and is a useful shortcut to know. This can be done for any block, not just numbers. Plug the block for 5 into the radius slot.</li> </ol><p>Here's how the touch event handler should look:</p> <p><img src="/sites/all/files/ai2tutorials/paintPot1/PaintPotTouchHandler.png" /></p> <p>Try out what you have so far on the phone. Touch a color button. Now touch the canvas, and your finger should leave a spot at each place you touch. Touching the Wipe button should clear your drawing.</p> <h4 class="ai-header">Add Drag Events</h4> <p>Finally, add the drag event handler. Here's the difference between a touch and a drag:</p> <ul><li>A touch is when you place your finger on the canvas and lift it without moving it.</li> <li>A drag is when you place your finger on the canvas and move your finger while keeping it in contact.</li> </ul><p>When you drag your finger across the screen, it appears to draw a giant, curved line where you moved your finger. What you're actually doing is drawing hundreds of tiny straight lines: each time you move your finger, even a little bit, you extend the line from your finger's immediate last position to its new position.</p> <p>A drag event comes with 6 arguments. These are three pairs of x and y coordinates that show:</p> <ul><li>The position of your finger back where the drag started.</li> <li>The current position of your finger.</li> <li>The immediately previous position of your finger.</li> </ul><p>There's also a sprite, which we'll ignore for this tutorial.</p> <p>Now make dragging draw a line between the previous position and the current position by creating a drag handler:</p> <ol><li>From the <span style="font-style:italic;">DrawingCanvas</span> drawer, drag the <span class="eventblock">when DrawingCanvas.Dragged</span> block to the workspace.</li> <li>Also from the <span style="font-style:italic;">DrawingCanvas</span> drawer, drag the <span class="callblock-ai2">call DrawingCanvas.DrawLine</span> block into the <span class="eventblock">do</span> slot of the <span class="eventblock">when DrawingCanvas.Dragged</span> block.</li> <li>Drag a <span class="getblock">get</span> block to the open slots in <span class="eventblock">when DrawingCanvas.Dragged</span> and select the corresponding value: <strong>x1</strong> and <strong>y1</strong> should be <strong>prevX</strong> and <strong>prevY</strong>; <strong>x2</strong> and <strong>y2</strong> should be <strong>currentX</strong> and <strong>currentY</strong>.</li> </ol><p>Here's the result:</p> <p><img src="/sites/all/files/ai2tutorials/paintPot1/PaintPotDragHandler.png" /></p> <p>Test your work by trying it on the phone: drag your finger around on the screen to draw lines and curves. Touch the screen to make spots. Use the Wipe button to clear the screen.</p> <p>In <a href="/ai2/paintpot-part2">PaintPot Part 2</a>, you'll see how to use global variables to create dots of different sizes.</p> <h4 class="ai-header">Review</h4> <p>Here are some of the ideas covered in this tutorial:</p> <ul><li>You can use Screen Arrangement components to specify screen layouts other than just placing components one under the other.</li> <li>The <strong>Canvas</strong> component lets you draw on it. It can also sense touches and drags.</li> <li>Some event handlers are called with information about the event, such as the coordinates of where the screen was touched. This information is represented by arguments. When you select an event handler that has arguments, App Inventor creates <span class="argblock">value</span> blocks for these and places them in the My Definitions drawer.</li> </ul><h4 class="ai-header">Scan the Sample App to your Phone</h4> <p>Scan the following barcode onto your phone to install and run the sample app. </p><p><img src="/sites/all/files/tutorials/paintPot1/PaintPotBarcode.png" /></p> <p>Or <a href="/sites/all/files/ai2tutorials/paintPot1/PaintPot.apk">download the apk</a></p> <h4 class="ai-header">Download Source Code</h4> <p>If you'd like to work with this sample in App Inventor, download the <a href="/sites/all/files/ai2tutorials/paintPot1/PaintPot.aia">source code</a> to your computer, then open App Inventor, go to the My Projects page, and choose <b>More Actions | Upload Source</b>.</p> </span></p></div></div></div><section class="field field-name-field-version field-type-taxonomy-term-reference field-label-above view-mode-rss clearfix"> <h2 class="field-label">Tutorial Version:&nbsp;</h2> <ul class="field-items"> <li class="field-item even"> <a href="/tutorial-version/app-inventor-2" typeof="skos:Concept" property="rdfs:label skos:prefLabel" datatype="">App Inventor 2</a> </li> </ul> </section> <section class="field field-name-field-tutorial-difficulty field-type-taxonomy-term-reference field-label-above view-mode-rss clearfix"> <h2 class="field-label">Tutorial Difficulty:&nbsp;</h2> <ul class="field-items"> <li class="field-item even"> <a href="/tutorial-difficulty/basic" typeof="skos:Concept" property="rdfs:label skos:prefLabel" datatype="">Basic</a> </li> </ul> </section> <section class="field field-name-field-tutorial-type field-type-taxonomy-term-reference field-label-above view-mode-rss clearfix"> <h2 class="field-label">Tutorial Type:&nbsp;</h2> <ul class="field-items"> <li class="field-item even"> <a href="/tutorial-type/drawing-canvas" typeof="skos:Concept" property="rdfs:label skos:prefLabel" datatype="">Drawing Canvas</a> </li> </ul> </section> Wed, 03 Jul 2013 14:47:23 +0000 joanie 357 at http://dev-explore.appinventor.mit.edu http://dev-explore.appinventor.mit.edu/ai2/paintpot-part1#comments Colored Dots http://dev-explore.appinventor.mit.edu/content/colored-dots <div class="field field-name-body field-type-text-with-summary field-label-hidden view-mode-rss"><div class="field-items"><div class="field-item even" property="content:encoded"><style> <!--/*--><![CDATA[/* ><!--*/ li { padding-bottom: 7px; } .basicblock { border: 1px dashed #7AA81C; padding-left: 4px; padding-right: 4px; padding-top: 1px; padding-bottom: 1px; background-color: #E7F2CB; font-size: 9pt; text-wrap: suppress; } .callblock { border: 1px dashed #000000; padding-left: 4px; padding-right: 4px; padding-top: 1px; padding-bottom: 1px; background-color: #E0D1FF; font-size: 9pt; text-wrap: suppress; } .argblock { border: 1px dashed #000000; padding-left: 4px; padding-right: 4px; padding-top: 1px; padding-bottom: 1px; background-color: #E5E5FF; font-size: 9pt; text-wrap: suppress; } .textblock { border: 1px dashed #000000; padding-left: 4px; padding-right: 4px; padding-top: 1px; padding-bottom: 1px; background-color: #FADAA0; font-size: 9pt; text-wrap: suppress; } .setblock { border: 1px dashed #000000; padding-left: 4px; padding-right: 4px; padding-top: 1px; padding-bottom: 1px; background-color: #C1D5F8; font-size: 9pt; text-wrap: suppress; } .controlblock { border: 1px dashed #000000; padding-left: 4px; padding-right: 4px; padding-top: 1px; padding-bottom: 1px; background-color: #FAEDBB; font-size: 9pt; text-wrap: suppress; } /*--><!]]>*/ </style><h2 class="ai-header"><span style="color:green;">Colored Dots</span>: Creating Apps with Multiple Screens</h2> <p>This tutorial shows how to create apps that have multiple screens. In App Inventor, you can have a screen open a second screen. Later, the second screen can return to the screen that opened it. You can have as many screens as you like, but each screen closes by returning to the screen that opened it. The screens can share information by passing and returning values when they open and close. The screens also share the same TinyDB data, which they can use to store and share values.</p> <p>Building an app with multiple screens is a lot like creating several individual apps. Every screen that you create has its own components in the Designer window. In the Blocks Editor, you will be able to see only the components of the screen currently selected in the Designer. Similarly, the blocks of code related to a screen cannot refer to blocks of code in another screen.</p> <p>This program, ColoredDots, has two screens. ColoredDots is similar to <a href="http://explore.appinventor.mit.edu/content/paintpot-part-1">PaintPot</a>, but it uses a second screen to let the user create new colors by providing numerical values for the red, green, and blue color composition (RGB). In the PaintPot app, a user can only paint with one of the three predefined colors. Adding more colors to Paintpot would have required new buttons on the screen, reducing the amount of space available for painting. In ColoredDots, the new color is chosen on a second screen called Brush_Picker. Once a new color has been created in this second screen, its value is passed back to the first screen. You can also save and name the colors you create in the second screen, then use the saved colors later when painting. By using ListPicker to store the colors you create, it eliminates the need for the user to remember the name of the color they saved and spell it correctly in accessing it again. This makes the database of stored colors more accessible, making it easier to share the app among a group of people.</p> <p>Here are the two screens for the ColoredDots app:</p> <p><img src="/sites/all/files/tutorials/coloredDots/brush_picker.PNG" style="float:right;" /></p> <p><img src="/sites/all/files/tutorials/coloredDots/screen1.PNG" /></p> <h4 class="ai-header">Objectives</h4> <p>By the end of this tutorial, you should have a understanding of:</p> <ul><li>How to make an app with multiple screens.</li> <li>How to pass values from one screen to another via <b>TinyDB</b>.</li> <li>How to fill and use the <b>ListPicker</b> element.</li> </ul><h4 class="ai-header">Building the Main Screen (Screen1)</h4> <p>You start building a multiscreen app by creating a new project, just as with any other app. As usual, App Inventor automatically creates the main screen and names it <b>Screen1</b> and you can add components. Here's the Designer and the Components panel when all the components for <b>Screen1</b> have been added.</p> <p><img src="/sites/all/files/tutorials/coloredDots/screen1designer_0.PNG" /></p> <p>The components are:</p> <table><tr style="background-color: #EFEFEF; font-weight: bold;"><td> Component Type </td> <td> Palette Group </td> <td> What you'll name it </td> <td> Purpose of Component </td> <td> Component Settings </td> </tr><tr><td> <b>Label</b> </td> <td>Basic</td> <td style="color:green;">TitleLabel</td> <td>Shows the title "Paint with Colored Dots"</td> <td></td> </tr><tr><td> <b>Label</b> </td> <td>Basic</td> <td style="color:green;">ColorLabel</td> <td>Shows the text "Current Color"</td> <td></td> </tr><tr><td> <b>Label</b> </td> <td>Basic</td> <td style="color:green;">ColorSample</td> <td>Blank label whose background color is the current color</td> <td></td> </tr><tr><td> <b>Label</b> </td> <td>Basic</td> <td style="color:green;">DotSizeLabel</td> <td>Shows the text "Dot size"</td> <td></td> </tr><tr><td> <b>Label</b> </td> <td>Basic</td> <td style="color:green;">DotSizeValue</td> <td>Shows the current dot size</td> <td></td> </tr><tr><td> <b>Canvas</b> </td> <td>Basic</td> <td style="color:green;">Canvas1</td> <td>Shows dots at the places you touch</td> <td></td> </tr><tr><td> <b>Button</b> </td> <td>Basic</td> <td style="color:green;">EraseButton</td> <td>Clears the canvas</td> <td>Set text to "Erase"</td> </tr><tr><td> <b>Button</b> </td> <td>Basic</td> <td style="color:green;">openBrushPicker</td> <td>Launches the second screen</td> <td>Shows the text "Customize Brush"</td> </tr><tr><td> <b>ListPicker</b> </td> <td>Basic</td> <td style="color:green;">ListPicker1</td> <td>Loads the list of colors from the data base</td> <td>Shows the text "Stored Color"</td> </tr><tr><td> <b>TinyDB</b> </td> <td>Basic</td> <td style="color:green;">TinyDB1</td> <td>Stores color names and values</td> </tr></table><p>We'll look at the blocks for <b>Screen1</b> below. But first let's add the other screen.</p> <h4 class="ai-header">Adding a second screen</h4> <p>To add a new screen to your app, click the Add Screen button in the top toolbar of the Designer window. A dialog window will appear, in which you can provide a name for the new screen.</p> <p><img src="/sites/all/files/tutorials/coloredDots/newscreenname_0.PNG" style="float:right; width:250px;" /></p> <p><img src="/sites/all/files/tutorials/coloredDots/addscreen.png" style="width:400px;" /></p> <pre class="ai-box"><b>Note:</b> You should make the name of the new screen something meaningful when you add it. Do that now, because once a screen has been added, its name cannot be changed -- the Rename button for the screen component itself is disabled -- it's good to have meaningful names for the parts of your program. One limitation here is that <b>Screen1</b> cannot be renamed. Remember also that the screen's title (shown in the title bar when the app is running) is different from its name. You can change the screen title in the Properties pane.</pre><p>When you create a new screen, the Designer window switches to display it. Initially there will be no components, just like with a new app, and you add new components by dragging them from the Palette, just as with any screen. Here's the Designer window for the second screen, named <b>Brush_Picker</b>, after the components have been added. Notice that <b>Brush_Picker</b> is a dark green color, meaning <b>Brush_Picker</b> is the current screen.</p> <p><img src="/sites/all/files/tutorials/coloredDots/brushpickerdesigner.PNG" /></p> <p>The components for the brush picker screen are:</p> <table><tr style="background-color: #EFEFEF; font-weight: bold;"><td> Component Type </td> <td> Palette Group </td> <td> What you'll name it </td> <td> Purpose of Component </td> </tr><tr><td> <b>Label</b> </td> <td>Basic</td> <td style="color:green;">RedLabel</td> <td>Shows the text "Red"</td> </tr><tr><td> <b>TextBox</b> </td> <td>Basic</td> <td style="color:green;">Red</td> <td>For entering the amount of red in the color (0-255)</td> </tr><tr><td> <b>Label</b> </td> <td>Basic</td> <td style="color:green;">GreenLabel</td> <td>Shows the text "Green"</td> </tr><tr><td> <b>TextBox</b> </td> <td>Basic</td> <td style="color:green;">Green</td> <td>For entering the amount of green in the color (0-255)</td> </tr><tr><td> <b>Label</b> </td> <td>Basic</td> <td style="color:green;">BlueLabel</td> <td>Shows the text "Blue"</td> </tr><tr><td> <b>TextBox</b> </td> <td>Basic</td> <td style="color:green;">Blue</td> <td>For entering the amount of blue in the color (0-255)</td> </tr><tr><td> <b>Label</b> </td> <td>Basic</td> <td style="color:green;">DotRadius</td> <td>Shows the text "Dot size"</td> </tr><tr><td> <b>TextBox</b> </td> <td>Basic</td> <td style="color:green;">RadiusTextBox</td> <td>Shows the current dot size</td> </tr><tr><td> <b>Button</b> </td> <td>Basic</td> <td style="color:green;">TestColorButton</td> <td>Press to create the new color and prompts the user to store this color</td> </tr><tr><td> <b>Label</b> </td> <td>Basic</td> <td style="color:green;">LabelTestColorSample</td> <td>Blank label whose background color is the new color</td> </tr><tr><td> <b>Canvas</b> </td> <td>Basic</td> <td style="color:green;">Canvas1</td> <td>Displays the size and color of the test color</td> </tr><tr><td> <b>Button</b> </td> <td>Basic</td> <td style="color:green;">ResetColorButton</td> <td>Resets all the values to the default color, black</td> </tr><tr><td> <b>Button</b> </td> <td>Basic</td> <td style="color:green;">ReturnToPainting</td> <td>Returns to the main screen with the new color and dot size</td> </tr><tr><td> <b>Notifier</b> </td> <td>Other stuff</td> <td style="color:green;">Notifier1</td> <td>Shows a dialog for saving the color and entering a color name</td> </tr><tr><td> <b>TinyDB</b> </td> <td>Basic</td> <td style="color:green;">TinyDB1</td> <td>Stores color names and values</td> </tr></table><p>Here and in general with multiple screen apps, only the components that belong to the current screen (in this case <b>Brush_Picker</b>) are shown in the Designer and the Components pane. You can switch between screens by pressing the <b>Brush_Picker</b> and the <b>Screen1</b> buttons, and the view in the Designer will show the corresponding screen. The same is true for the Blocks Editor: When you're working on a screen you'll see only the blocks for that screen.</p> <pre class="ai-box">None of the components, variable definitions, and procedures that you define in one screen will be accessible from any other screen. We'll see below how to pass information between screens.</pre><pre class="ai-warning">Warning: When you switch between screens, you are effectively telling the Blocks Editor to load a new project, and this takes a little time. Wait until the Blocks Editor is done loading the blocks for the new screen before changing things. Most especially, wait until the new screen has finished loading before clicking on blocks or links with the mouse. If you don't wait, you may get errors, or even lose blocks from your project.</pre><h4 class="ai-header">Blocks for the main screen (Screen1)</h4> <p>The <b>Screen1</b> is essentially a drawing program. When you touch the Canvas, the app draws a dot of the current radius and color. The color is specified by the background of the <b>ColorSample</b> label. The erase button clears the canvas. When the screen opens, it initializes the radius to 3 and the color to black. Here are the corresponding blocks:</p> <p><img src="/sites/all/files/tutorials/coloredDots/screen1basicblocks.PNG" /></p> <p>It is worth noting that the <span class="basicblock">Initialize</span> block uses the procedure <span class="callblock">TinyDB1.StoreValue</span> and sets the ListPicker to <span class="callblock">populateList</span> using the <span class="setterblock">set ListPicker1.Elements to</span> block. Each of these actions will be discussed in more detail later. Basically, when the screen starts, it stores the default color, Black, and adds that to the list of colors that can be selected using the ListPicker. </p> <pre class="ai-testing"><b>Testing the behavior.</b>Test to make sure the drawing behavior acts as you expect it to. You won't be able to add new colors yet, but see what happens when you try to draw dots of the page.</pre><h4 class="ai-header">Communicating with the brush picker screen</h4> <p>The multiple screen aspect of the app involves getting the "new brush": the new color and the new dot radius. It's the job of <b>Brush_Picker</b> to create these values and return these to <b>Screen1</b> as a list of three items: the color, the dotsize, and the total number of colors stored. The number of colors is necessary for creating the list that ListPicker will reference. We'll see how <b>Brush_Picker</b> does this below, but from the perspective of <b>Screen1</b>, all it needs to do is open <b>Brush_Picker</b> and get the result.</p> <p>Here's how this happens: when the Customize Brush button is pressed, <b>Screen1</b> uses <span class="" controlblock="">open another screen with start value</span> to open <b>Brush_Picker</b>. When the user finishes with Brush_Picker, it will signal the other screen closed event, which provides the name of the screen (here Brush_Picker) and the value returned (here the three-element list). The event handler for <b>Screen1</b> extracts the three items from the list and sets the ColorSample background and the DotSizeValue text properties. It also calls the procedure <span class="callblock">populateList</span>, which is defined below. Here are the blocks:</p> <p><img src="/sites/all/files/tutorials/coloredDots/screen1communicating.PNG" /></p> <p>ColoredDots uses <span class="controlblock">open another screen with value</span> to open <b>Brush_Picker</b> with values passed to it from <b>Screen1</b>. The other screen then accesses these opening values using <span class="controlblock">get start value</span> blocks. In general, a screen opens another screen with <span class="controlblock">open another screen</span> and gets a result back though the <span class="controlblock">when other screen closed</span> event. In this case, the values are passed from <b>Screen1</b> to <b>Brush_Picker</b> so the app can keep track of how many colors are stored and what the current values are.</p> <pre class="ai-testing"><b>Testing the behavior.</b> If you want to make sure that your blocks for opening a new screen are working, you will have to package the app to your phone or emulator. App Inventor does not currently allow live development for multi-screen apps, so make sure you package the phone before trying to test the behavior.</pre><h4 class="ai-header">Sharing data via TinyDB</h4> <p>Besides opening screens and returning values, the different screens in a multiple screen app can communicate through TinyDB. To do this, give every screen its individual TinyDB component. Even though these will be "different" TinyDB components, they will in fact all share the same keys and values: If one screen stores a value under a key, the other screen can get that value by using the same key.</p> <p>ColoredDots uses TinyDB to let you name the colors you create and save them to later use. The saving and naming will be done in <b>Brush_Picker</b>, as shown in the blocks later. When you open ListPicker (labelled Stored Color) in <b>Screen1</b>, the app uses opens the list of colors that you have stored for you to choose one and then sets the drawing color to the result. The elements are added to this list by creating the procedure <span class="callblock">populateList</span>. As shown in these blocks, <span class="callblock">populateList</span> iterates through the all of the stored entries in the database up to the number of stored colors and adds them to the list tinyDBlist. It returns this list, which ListPicker1 points to.</p> <p><img src="/sites/all/files/tutorials/coloredDots/screen1populatelist.PNG" /></p> <p>When ListPicker is opened, you will see a list of all the colors you created. <span class="basicblock">ListPicker1.AfterPicking</span> sets the Color value stored for that name to be the current drawing color, as shown here. </p> <p><img src="/sites/all/files/tutorials/coloredDots/screen1listpicker.PNG" /></p> <h4 class="ai-header">Blocks for the Brush_Picker screen</h4> <p>The main job of <b>Brush_Picker</b> is to create a color from the red-green-blue values entered in the text boxes and provide that color to <b>Screen1</b>. When you click ReturnToPainting the new color, the new dot size (taken from the RadiusTextBox), and the total number of colors are returned to <b>Screen1</b> as a three-item list.As mentioned above, when Brush_Picker is open, Screen1 passes it values of the current color, the number of colors, and the current dot radius size. <b>Brush_Picker</b> uses <span class="controlblock">get start value</span> when it is initialized to access these values.</p> <p>When you click the TestColorButton, the color is created for you as the background of LabelTestColorSample and the Canvas shows a circle of the appropriate size and color. To return the list to Screen1, <b>Brush_Picker</b> uses <span class="controlblock">close screen with value</span>, which takes as an argument the value to be returned (in this case, the list). When a screen closes, the app returns to the screen that opened it.</p> <p>Here are the blocks that do this. <b>Brush_Picker</b> uses the procedures <span class="callblock">CheckColor</span> and <span class="callblock">LimitRange</span> to ensure that the values entered in the text boxes are valid numbers for colors and dot size. We'll examine these procedure below."</p> <p><img src="/sites/all/files/tutorials/coloredDots/brushpickercommunicate.PNG" /></p> <p>When TestColorButton is clicked, is displays the created color. Notifier1 is then used to give you a choice to save the color or cancel using the <span class="basicblock">Notifier1.ShowChooseDialog</span> block. The response from this will trigger further Notifier events so that you can save the color.</p> <p><img src="/sites/all/files/tutorials/coloredDots/brushpickertestcolor.PNG" /></p> <p>The next blocks show how Brush_Picker associates a name with a color for use by Screen1. The <span class="basicblock">Notifier1.ShowChooseDialog</span> block triggers a <span class="basicblock">Notifier1.AfterChoosing</span> event. In these blocks, the <b>ifelse</b> block checks the response to whether or not the color should be saved. If the response is "OK," <span class="basicblock">Notifier1.AfterChoosing</span> calls <span class="basicblock">Notifier1.ShowTextDialog</span> which prompts you to store a name for this color.</p> <p>Once you make your entry, the color is stored with two tags two ways in TinyDB1. First, it stores the name with the current number of colors as the key. This is used when iterating through the list of colors for ListPicker in <b>Screen1</b> so that the names will be displayed for the user. Secondly, the color is stored in TinyDB, using the name you entered as a key. <b>Screen1</b> can then retrieve the color using its own TinyDB component and access it via the stored name as chosen in ListPicker.</p> <p><img src="/sites/all/files/tutorials/coloredDots/brushpickerstorecolor.PNG" /></p> <p>The Reset button allows the user to clear all of the entries in the red, green, and blue fields so they can start over easily. The blocks for this are shown here:</p> <p><img src="/sites/all/files/tutorials/coloredDots/brushpickerresetcolor.PNG" /></p> <h4 class="ai-header">Limiting numbers to a range</h4> <p>The only thing left is to show how <b>Brush_Picker</b> checks that it's using good values for colors and dot size. Each of the red, green, blue values should be a number between 0 and 255. But you could have entered anything in those text boxes. The <span class="callblock">checkColor</span> procedure takes a value and limits its range to between 0 and 255: If it's less than 0 (or not a number at all) the result will be 0. It it's greater than 255, the result will be 255:</p> <p><img src="/sites/all/files/tutorials/coloredDots/checkColor.png" /></p> <p>The final bit is <span class="callblock">LimitRange</span>. This is a general procedure that takes an input, a lower limit, and an upper limit, and restricts the input to lie within that range (and it returns the lower limit if the input is not a number). The procedure is simple, but tricky: To restrict the range, take the maximum of the input and the lower limit, then take the minimum of the result and the upper limit. This programming "trick" has little to do with multiple screens or App Inventor. You might want to take a few moments to convince yourself that it really works.</p> <p><img src="/sites/all/files/tutorials/coloredDots/LimitRange.png" /></p> <h4 class="ai-header">Comments on multiple screens</h4> <p>You can have many screens in an App Inventor app, but a screen always returns to the screen that opened it. On the other hand, you can get the effect of screens switching to arbitrary other screen by setting up a "manager screen" that is used for opening all the other screens. When a screen wants to switch, it returns to the manager with a value saying which screen to open next.</p> <pre class="ai-testing"><b>Testing the behavior.</b> In the current version of App Inventor, it is not yet possible to test a multiple-screen app in live development mode. You can test each screen separately, but you cannot test the communication between two screens. When try to switch between screens, you'll get an error message. To test whether the screens are properly communicating, you'll need to <b>Package for Phone</b> and open the installed app.</pre><h4 class="ai-header">Further exploration</h4> <p>Now that you are able to create your own colors and access them for drawing, try some variations!</p> <ul><li>Make Brush_Picker warn the user if they are trying to store a color with the same name as something that has already been stored (e.g. don't let them make two colors named "red"). </li><li>Have the starting color be the last one that the user was using in the app instead of always starting with black. </li></ul><h4 class="ai-header">Summary</h4> <p>In this tutorial you have learned:</p> <ul><li>How to make an app with multiple screens</li> <li>How to share data between those two screens using <b>TinyBD</b></li> <li>How to use a counter to add all of the values in <b>TinyDB</b> to add to a list.</li> <li>How to use <b>ListPicker</b> to select from a list of items</li> </ul><pre class="ai-box">This tutorial is based on work by Eni Mustafaraj of Wellesley College. Done with <span style="color:black;">Colored Dots</span>? Return to the other tutorials <a href="/tutorials">here</a>.</pre></div></div></div><section class="field field-name-field-version field-type-taxonomy-term-reference field-label-above view-mode-rss clearfix"> <h2 class="field-label">Tutorial Version:&nbsp;</h2> <ul class="field-items"> <li class="field-item even"> <a href="/tutorial-version/app-inventor-1" typeof="skos:Concept" property="rdfs:label skos:prefLabel" datatype="">App Inventor 1</a> </li> </ul> </section> <section class="field field-name-field-tutorial-difficulty field-type-taxonomy-term-reference field-label-above view-mode-rss clearfix"> <h2 class="field-label">Tutorial Difficulty:&nbsp;</h2> <ul class="field-items"> <li class="field-item even"> <a href="/tutorial-difficulty/advanced" typeof="skos:Concept" property="rdfs:label skos:prefLabel" datatype="">Advanced</a> </li> </ul> </section> <section class="field field-name-field-tutorial-type field-type-taxonomy-term-reference field-label-above view-mode-rss clearfix"> <h2 class="field-label">Tutorial Type:&nbsp;</h2> <ul class="field-items"> <li class="field-item even"> <a href="/tutorial-type/drawing-canvas" typeof="skos:Concept" property="rdfs:label skos:prefLabel" datatype="">Drawing Canvas</a> </li> <li class="field-item odd"> <a href="/tutorial-type/multiple-screens" typeof="skos:Concept" property="rdfs:label skos:prefLabel" datatype="">Multiple Screens</a> </li> </ul> </section> Fri, 14 Jun 2013 15:47:16 +0000 aaron 310 at http://dev-explore.appinventor.mit.edu http://dev-explore.appinventor.mit.edu/content/colored-dots#comments PaintPot (Part 1) http://dev-explore.appinventor.mit.edu/content/paintpot-part-1 <div class="field field-name-body field-type-text-with-summary field-label-hidden view-mode-rss"><div class="field-items"><div class="field-item even" property="content:encoded"><p>This tutorial has two parts: <a href="/content/paintpot-part-1">Part 1</a> | <a href="/content/paintpot-part-2">Part 2</a> </p> <p>This tutorial introduces the <strong>Canvas</strong> component for creating simple two-dimensional graphics. You'll build an app that lets you draw on the phone screen in different colors.</p> <pre class="ai-box"><strong>Historical note</strong>: PaintPot was one of the first programs developed to demonstrate the potential of personal computers, as far back as the 1970s.</pre><p><a href="http://cs.usfca.edu/~wolber/appinventor/bookSplits/ch2PaintPot.pdf">Download Book Chapter PDF</a></p> <h4>What you're building</h4> <p><img style="float:right;margin:5px;" src="/sites/all/files/tutorials/paintPot1/PaintPotPart1PhoneImage.png" /></p> <p>With the <span style="font-style:italic;">PaintPot</span> app, you can:</p> <ul><li>Dip your finger into a virtual paint pot to draw in that color.</li> <li>Drag your finger along the screen to draw a line.</li> <li>Tap the screen to make dots.</li> <li>Use the button at the bottom to wipe the screen clean.</li> <li>Include an image as a drawing background.</li> </ul><p><span style="font-style:italic;"> <p>This tutorial assumes that you have completed the <span style="font-style:italic;">HelloPurr</span> tutorial. It introduces the following App Inventor concepts:</p> <ul><li>The <strong>Canvas</strong> component for drawing.</li> <li>Controlling screen layout with <strong>Arrangement</strong> components.</li> <li>Event handlers that take arguments.</li> <li>Variables.</li> </ul><h4 class="ai-header">Before starting</h4> <p>Make sure your computer and your phone are set up to use App Inventor. Start a new project in the Designer window, and name it <span style="font-style:italic;">"PaintPot"</span>. Open the Blocks Editor, click <strong>Connect to Phone</strong>, and make sure the phone has started the App Inventor app.</p> <h4 class="ai-header">Screen title</h4> <p>To get started, go to the Properties panel on the right of the Designer and change the screen <strong>Title</strong> to "PaintPot". You should see this change on phone, with the new title showing in the title bar.</p> <p>There are three names in App Inventor, and it's easy to confuse them:</p> <ol><li>The name you choose for your project as you work on it (in this case, <span style="font-style:italic;">PaintPot</span>). This will also be the name of the application if you package it for the phone.</li> <li>The name "Screen1", which is the name of the <strong>Screen</strong> component. You'll see it listed in the Components panel in the Designer. You can't change the name of the Screen component in the current version of App Inventor.</li> <li>The <strong>Title</strong> property of the screen, which is what you'll see in the phone's title bar. Title is a property of the <strong>Screen</strong> component. The Title starts out being "Screen1", which is what you used in <span style="font-style:italic;">HelloPurr</span>. However, you can change it, as you're doing for <span style="font-style:italic;">PaintPot</span>. To reiterate, the name and the title of Screen1 are initially the same, but you can change the title if you want.</li> </ol><h4 class="ai-header">Set up the Components</h4> <p>You'll use these components to make <span style="font-style:italic;">PaintPot</span>:</p> <ul><li>Three <strong>Buttons</strong> for selecting red, blue, or green paint, and another button for wiping the drawing.</li> <li>A <strong>Canvas</strong>, the drawing surface. This canvas has a <strong>BackgroundImage</strong>, which is <a href="/sites/all/files/tutorials/helloPurr/kitty.png">this kitty</a> from the <span style="font-style:italic;">HelloPurr</span> tutorial. You can also draw on a blank canvas. That's just a canvas without a background image.</li> <li>There's also a component you don't see: you use a <strong>HorizontalArrangement</strong> to make the three color buttons line up.</li> </ul><p>That makes five components in all. Let's get them and build the app.</p> <h4 class="ai-header">Color Buttons</h4> <ul><li>Drag a <strong>Button</strong> component onto the Viewer and change the button's <strong>Text</strong> attribute to "Red" and make its <strong>BackgroundColor</strong> red.</li> <li>Click on <span style="font-style:italic;">Button1</span> in the components list in the Viewer to highlight it (it might already be highlighted) and use the <strong>Rename...</strong> button to change its name from "Button1" to "ButtonRed".</li> <li>Similarly, make two more buttons for blue and green, named "ButtonBlue" and "ButtonGreen", placing them vertically under the red button.</li> </ul><p>Here's how this should look in the designer, with the button names appearing in the list of project components. In this project, you're changing the names of the components rather than leaving them as the default names as you did with <span style="font-style:italic;">HelloPurr</span>. Using meaningful names makes your projects more readable to yourself and others.</p> <p><img src="/sites/all/files/tutorials/paintPot1/PaintPotThreeButtonsVertically.png" /></p> <p>You should also see the three buttons on the phone screen.</p> <h4 class="ai-header">Layout with Screen Arrangement</h4> <p>You should now have three buttons, one above the other. The next step is to make them line up horizontally. You do this using a <strong>HorizontalArrangement</strong> component.</p> <ol><li>From the Palette's Screen Arrangement category, drag out a <strong>HorizontalArrangement</strong> component and place it under the buttons. Change the name of this component from "HorizontalArrangement1" to "ThreeButtons".</li> <li>In the Properties panel, change the <strong>Width</strong> of <span style="font-style:italic;">ThreeButtons</span> to "Fill Parent..." so that it fills the entire width of the screen.</li> <li>Move the three buttons side by side into the <strong>HorizontalArrangement</strong> component. <strong>Hint</strong>: You'll see a blue vertical line that shows where the piece you're dragging will go.</li> </ol><p>If you look in the list of project components, you'll see the three buttons indented under the <span style="font-style:italic;">ThreeButtons</span> to show that they are now its subcomponents. Notice that all the components are indented under <span style="font-style:italic;">Screen1</span>.</p> <p><img src="/sites/all/files/tutorials/paintPot1/PaintPotThreeButtonsHorizontally.png" /></p> <p>You should also see your three buttons line up in a row on the phone screen, although things might not look exactly as on the Designer. For example, the Arrangement's outline shows in the Designer but not on the phone.</p> <p>In general, you use Screen Arrangement to create simple vertical or horizontal layouts. You can create more complex layouts by nesting Screen Arrangement components. There is also a <strong>TableArrangement</strong> component (not covered in this tutorial).</p> <h4 class="ai-header">Canvas and wipe button</h4> <p>The final two components are the canvas and the wipe button.</p> <ol><li>From the Palette's Basic category drag a <strong>Canvas</strong> component onto the Viewer. Change its name to "DrawingCanvas". Set its <strong>Width</strong> to "Fill Parent" and set its <strong>Height</strong> to 300 pixels.</li> <li>Add a Background Image to the <strong>Canvas</strong>. Click on the field containing "None..." next to <strong>BackgroundImage</strong> in the canvas's Properties panel. You can use the same kitty.png file, if you still have it on your desktop from an earlier tutorial. Or you can use another image.<br /><pre class="ai-box">You can use any image you like, but you'll get the best results if the size of the image (in pixels) is close to the size at which you'll be showing it on the phone. Also, large images will take a long time to load, and might exceed the memory capacity of the phone allocates for applications.</pre></li> <li>From the Palette, drag the final button onto the screen, placing it under the canvas. Change its <strong>id</strong> to "ButtonWipe" and change its <strong>Text</strong> attribute to "Wipe".</li> </ol><p>You've now completed the steps to set the appearance of your app. Here's how this should look in the Designer. Next, you'll define how the components behave.</p> <p><img src="/sites/all/files/tutorials/paintPot1/PaintPotDesigner.png" /></p> <h4 class="ai-header">Add behaviors to the components</h4> <p>The Blocks Editor should already be open. First set up the buttons that change the paint color. Later you will add blocks to decide what happens when someone touches or drags the screen.</p> <h4 class="ai-header">Add button event handlers</h4> <p>In the Blocks Editor:</p> <ol><li>Switch to the My Blocks column.</li> <li>Open the drawer for <span style="font-style:italic;">ButtonRed</span> and drag out the <span class="basicblock">when ButtonRed.Click </span> block.</li> <li>Open the <span style="font-style:italic;">DrawingCanvas</span> drawer. Drag out the <span class="setblock">set DrawingCanvas.PaintColor to </span> block (you may have to scroll the list of blocks in the drawer to find it) and place it in the <span class="basicblock">do</span> section of <span class="basicblock">when ButtonRed.Click </span>.</li> <li>Switch to the Built-In Column. Open the Colors drawer and drag out the block for the color Red and put it into <span class="setblock">set DrawingCanvas.PaintColor to </span>.</li> <li>Repeat steps 2-4 for the blue and green buttons.</li> <li>The final button to set up is the Wipe button. Switch back to the My Blocks column. Make a click event handler for <span style="font-style:italic;">ButtonWipe</span> by dragging <span class="basicblock">when ButtonWipe.Click </span> from the <span style="font-style:italic;">ButtonWipe</span> drawer. From the <span style="font-style:italic;">DrawingCanvas</span> drawer, drag <span class="callblock">call DrawingCanvas.Clear </span> and place it in the <span class="basicblock">do</span> area of the <span class="basicblock">when ButtonWipe.Click</span> block.</li> </ol><p>The blocks for the buttons should look like this:</p> <p><img src="/sites/all/files/tutorials/paintPot1/buttonsclick.PNG" /></p> <h4 class="ai-header">Add Touch-event Handlers</h4> <p>Now for the next step: drawing on the <strong>Canvas</strong>. You'll arrange things so that when you touch the canvas, you get a dot at the spot where you touch. If you drag your finger slowly along the canvas, it draws a line.</p> <ul><li>In the Blocks Editor, open the drawer for the canvas and drag the <span class="basicblock">when DrawingCanvas.Touched</span> block to the workspace. As soon as you drag the block out, the three plugs on the right automatically fill in with name blocks called <strong>x</strong>, <strong>y</strong>, and <strong>touchedSprite</strong>.</li> </ul><p>You've already seen button click events. Clicks are simple, because there's nothing to know about the click other than that it happened. Other event handlers such as <span class="basicblock">when ... Touched</span> need information about the event. In App Inventor, this information is expressed as the value of arguments associated with the event handler. For the <span class="basicblock">when ... Touched</span> event, the first two arguments stand for the x and y coordinates of where the touch happened. We'll save <strong>touchedSprite</strong> for a later tutorial.</p> <ul><li>For this touch event, make the canvas draw a small circle at the point with coordinates (x, y). Drag out a <span class="callblock">call DrawingCanvas.DrawCircle</span> command from the canvas drawer and place it in the <span class="basicblock">do</span> section of <span class="basicblock">when DrawingCanvas.Touched</span>.</li> </ul><p>On the right side of the <span class="callblock">call DrawingCanvas.DrawCircle</span> block are three sockets where you must specify values for the x and y coordinates where the circle should be drawn, and <strong>r</strong>, which is the radius of the circle. For <strong>x</strong> and <strong>y</strong>, you'll use values of the arguments that were supplied to the Touched handler:</p> <ol><li>Open the My Definitions drawer at the top of the column. Find the blocks for <span class="argblock">value x</span> and <span class="argblock">value y</span>. The blocks were automatically created when you dragged out the touch event handler block.</li> <li>Drag out the <span class="argblock">value x</span> and <span class="argblock">value y</span> blocks and plug them into the corresponding sockets in the <span class="basicblock">when DrawingCanvas.Touched</span> block. Make sure to drag the <span class="argblock">value</span> blocks, not the corresponding <span class="argblock">name</span> blocks; they look very similar.</li> <li>You'll also need to specify the radius of the circle to draw. Five (pixels) is a good value for this app. Click in a blank area of the screen to bring up the hover menu and select <strong>math</strong> (green). Select "123" from the dropdown list, to create a number block. Change the "123" to "5" and plug that in for the radius slot.</li> </ol><pre class="ai-box">You can also just type 5 followed by return, to create a number block with a value of 5. This is an example of <em>typeblocking</em>: if you start typing, the Blocks Editor shows a list of blocks whose names match what you are typing; if you type a number it creates a number block.</pre><p>Here's how the touch event handler should look:</p> <p><img src="/sites/all/files/tutorials/paintPot1/PaintPotTouchHandler.png" /></p> <p>Try out what you have so far on the phone. Touch a color button. Now touch the canvas, and your finger should leave a spot at each place you touch. Touching the Wipe button should clear your drawing.</p> <h4 class="ai-header">Add Drag Events</h4> <p>Finally, add the drag event handler. Here's the difference between a touch and a drag:</p> <ul><li>A touch is when you place your finger on the canvas and lift it without moving it.</li> <li>A drag is when you place your finger on the canvas and move your finger while keeping it in contact.</li> </ul><p>When you drag your finger across the screen, it appears to draw a giant, curved line where you moved your finger. What you're actually doing is drawing hundreds of tiny straight lines: each time you move your finger, even a little bit, you extend the line from your finger's immediate last position to its new position.</p> <p>A drag event comes with 6 arguments. These are three pairs of x and y coordinates that show:</p> <ul><li>The position of your finger back where the drag started.</li> <li>The current position of your finger.</li> <li>The immediately previous position of your finger.</li> </ul><p>There's also a sprite, which we'll ignore for this tutorial.</p> <p>Now make dragging draw a line between the previous position and the current position by creating a drag handler:</p> <ol><li>From the <span style="font-style:italic;">DrawingCanvas</span> drawer, drag the <span class="basicblock">when DrawingCanvas.Dragged</span> block to the workspace.</li> <li>Also from the <span style="font-style:italic;">DrawingCanvas</span> drawer, drag the <span class="callblock">call DrawingCanvas.DrawLine</span> block into the <span class="basicblock">do</span> slot of the <span class="basicblock">when DrawingCanvas.Dragged</span> block.</li> <li>Click on the My Definitions drawer. You should see the blocks for the arguments you need. Drag the corresponding value blocks to the appropriate slots in <span class="basicblock">when DrawingCanvas.Dragged</span>: <strong>x1</strong> and <strong>y1</strong> should be <strong>prevX</strong> and <strong>prevY</strong>; <strong>x2</strong> and <strong>y2</strong> should be <strong>currentX</strong> and <strong>currentY</strong>.</li> </ol><p>Here's the result:</p> <p><img src="/sites/all/files/tutorials/paintPot1/PaintPotDragHandler.png" /></p> <p>Test your work by trying it on the phone: drag your finger around on the screen to draw lines and curves. Touch the screen to make spots. Use the Wipe button to clear the screen.</p> <p>In <a href="/content/paintpot-part-2">PaintPot Part 2</a>, you'll see how to use global variables to create dots of different sizes.</p> <h4 class="ai-header">Review</h4> <p>Here are some of the ideas covered in this tutorial:</p> <ul><li>You can use Screen Arrangement components to specify screen layouts other than just placing components one under the other.</li> <li>The <strong>Canvas</strong> component lets you draw on it. It can also sense touches and drags.</li> <li>Some event handlers are called with information about the event, such as the coordinates of where the screen was touched. This information is represented by arguments. When you select an event handler that has arguments, App Inventor creates <span class="argblock">value</span> blocks for these and places them in the My Definitions drawer.</li> </ul><h4 class="ai-header">Scan the Sample App to your Phone</h4> <p>Scan the following barcode onto your phone to install and run the sample app. </p><p><img src="/sites/all/files/tutorials/paintPot1/PaintPotBarcode.png" /></p> <h4 class="ai-header">Download Source Code</h4> <p>If you'd like to work with this sample in App Inventor, download the <a href="/sites/all/files/tutorials/paintPot1/PaintPot.zip">source code</a> to your computer, then open App Inventor, go to the My Projects page, and choose <b>More Actions | Upload Source</b>.</p> </span></p></div></div></div><section class="field field-name-field-version field-type-taxonomy-term-reference field-label-above view-mode-rss clearfix"> <h2 class="field-label">Tutorial Version:&nbsp;</h2> <ul class="field-items"> <li class="field-item even"> <a href="/tutorial-version/app-inventor-1" typeof="skos:Concept" property="rdfs:label skos:prefLabel" datatype="">App Inventor 1</a> </li> </ul> </section> <section class="field field-name-field-tutorial-difficulty field-type-taxonomy-term-reference field-label-above view-mode-rss clearfix"> <h2 class="field-label">Tutorial Difficulty:&nbsp;</h2> <ul class="field-items"> <li class="field-item even"> <a href="/tutorial-difficulty/basic" typeof="skos:Concept" property="rdfs:label skos:prefLabel" datatype="">Basic</a> </li> </ul> </section> <section class="field field-name-field-tutorial-type field-type-taxonomy-term-reference field-label-above view-mode-rss clearfix"> <h2 class="field-label">Tutorial Type:&nbsp;</h2> <ul class="field-items"> <li class="field-item even"> <a href="/tutorial-type/drawing-canvas" typeof="skos:Concept" property="rdfs:label skos:prefLabel" datatype="">Drawing Canvas</a> </li> </ul> </section> Fri, 14 Jun 2013 15:43:28 +0000 aaron 305 at http://dev-explore.appinventor.mit.edu http://dev-explore.appinventor.mit.edu/content/paintpot-part-1#comments