Java Programming Computer Science 112
Recap: Swing You use Window Builder to put Widgets together on a Layout. User interacts with Widgets to produce Events. Code in the Client Listens for Events to know when to run. Client (or View) tells Logic (or Model) what happens. Full MVC splits Controller from View Client Listens (or Queries) for Logic to show change The Model may not touch the View
What can we draw on JFrame is the whole app JOtherStuff are useful widgets with dedicated functions JPanel is just a rectangle that does nothing so we can play with it If you come across "Canvas" in your searches, that is the AWT version. AWT is what came before Swing. Canvas is a better analogy than Panel though.
Made with Lymon A patch of screen that draws itself and can be moved around is called a Sprite A Sprite is a thing that you can see, so it is on the Client. Later, the Sprite will be associated with an Object in Logic so it can move around and do stuff. The JPanel is the area we are drawing in. The Sprites are how it draws.
A custom JPanel Start just like last time. Normal project Application Window MainClient Add a JPanel that doesn't fill the screen, and change its color so you can see it. Make a new class in Client called SpriteField that extends JPanel Change the class type of the generated bit in initialize()
Why am I doing this? Buttons and stuff know how to draw. You are making a new Widget and telling Java "Don't worry, I know how to draw this." super important During this process, you will get a few warnings and errors. Eclipse knows what to do if you hover over the error. (It wants some imports and default settings.)
You make the sprite Sprites are not Swing things. We are in appspecific code now. Make SpriteField's constructor make a RoundSprite. That is a normal new class like we've always done. It will have one method on the next slide We are going to have SpriteField (the JPanel) be in charge of making RoundSprites draw.
The Black Spot "2D" is the new version of the Graphics interface, so this cast is okay. When we cross in to our code, we don't need to anymore.
Pause to regroup JWidgets know how to draw themselves and do things JPanel is a blank template for us to do what we want We made a custom JPanel that is going to draw dots The dots are not JWidgets. We are using the Graphics "pen" directly. Graphics2D has lots of tools for hand drawing. paintcomponent = Java, DrawSprite = us
The hard part: Coordinates Graphics2D uses a pen that starts in the top left corner. To draw something it moves the pen using a "transform". It then hands the pen to the thing being drawn. This is the hard part: The thing being drawn doesn't know where he is. "x = 5" is totally different when you are in "object space" instead of "world space"
Code sketch for drawing For each thing I want to draw Apply transform for its position For each piece of it Apply transform for that piece Draw piece Undo piece transform Undo position transform Undo camera transform 0,0 Think of Mickey Mouse's silhouette.
And to draw one piece... Translate, Rotate, Center! TWO ways to picture this The pen moves Move to where you want to draw Twist the pen Move to the center of the ellipse The panel moves Slide the canvas Rotate the canvas around the pen Shift the canvas a little more
Add a position to RoundSprite Camera flip You have to add SetPosition, mx, and my yourself. See how the Sprite undid its transform fiddling? Note the 35,25. mx,my is where the sprite is in world coords. 35,25 is where this ellipse is in object coords.
Mouse interaction Put your love for Window Builder in your pocket for a minute It freaks out trying to add Event templates to a custom class. Change the class of your SpriteField back to JPanel in initialize() Add Handler in design mode Change class back Not so bad You could also just type it Newest Eclipse can do it
Promise I'll stop with this bit The Controller (the thing that handles all the events) can talk to the Model. That's how stuff gets made. The View is then just going to draw it. mlogic.createobjectat(tx, ty); mspritepanel.createspriteat(tx, ty); CreateObjectAt here is the advanced way required in Homework 2. It is to make a Shape that in turn makes a Sprite. For homework 1, you could instead go straight to the panel to make the Sprite directly. I won't know.
MVC Again If you createspriteat, you are done. When you createobjectat, the model needs to somehow tell the view that something has changed. Best is Observable Second best is MainClient.NotifyNewShape()
Then just add support for multiples ArrayList<RoundSprite> msprites = new ArrayList<RoundSprite>(); This use of "for-colon" or "foreachin" is a nice shortcut for an ArrayList of objects. It just saves you from counting from zero to size and then accessing each explicitly. Click made an Object in the Model Object hollered out that an Object was made Or since you are freshmen they can tell the Client singleton View listens for new object messages and makes a Sprite Our new Sprite JPanel draws all the sprites Oh, and call "repaint()" on the SpriteField whenever something changes.
Oh, tiny lie: Rotation is last thing But Imma make you do it. The "rotate" command is just like "translate" Have a newly created RoundSprite be made with a random "float mrotation". You now know: GUI widgets, coordinates in screen space and user space, custom drawing. Oh, and Java. Don't ever believe me when I say something is the last thing.
BasicStroke A Stroke is like the Pen that Graphics is using to draw. It can have a dash pattern, a thickness, and rules about joining other lines.
Color All operations on Graphics2D are permanent but not retroactive. g2.setstroke(tstroke); g2.setcolor(color.blue);
Wait, permanent? This is one area that Java just falls down on. There is no PushContext If you change any settings on the graphics object, you better: Change it back when you are done, like we did for the transform, which is easy. Make sure every single thing you draw explicitly sets color and stroke so nothing will ever carry over, which is hard.