340 likes | 342 Vues
Drawing. C Sc 335 Object-Oriented Programming and Design Rick Mercer. Outline. Drawing with a Graphics object Graphics and Graphics2D paintComponent and repaint draw and fill messages Strings, Lines, Rectangle, Ellipse, Polygons Colors Text and Fonts Drawing Images
E N D
Drawing C Sc 335 Object-Oriented Programming and Design Rick Mercer
Outline • Drawing with a Graphics object • Graphics and Graphics2D • paintComponent and repaint • draw and fill messages • Strings, Lines, Rectangle, Ellipse, Polygons • Colors • Text and Fonts • Drawing Images • Toolkit to convert jpg and gif files into Images
Drawing with a Graphics Object • The use of graphics is common among modern software systems • Java has strong support for graphics • coordinate system for Java graphics • drawing shapes such as lines, ovals, rectangles, ... • basic animation techniques • the use of color • the use of fonts • drawing images
The Coordinate System • A simple two-dimensional coordinate system exists for each graphics context or drawing surface • Each point on the coordinate system represents a single pixel • top left corner of the area is coordinate <0, 0> • // This string will be drawn 20 pixels right, • // 40 pixels down as the lower left corner; • // other shapes are upper right • g2.drawString("is in Panel1", 20, 40); • A drawing surface has a width and height • Anything drawn outside of that area is not visible
X <0, 0> x y <x, y> <width-1, height-1> Y The Coordinate System
Draw on a JPanel • Need to extend a class that extends JComponent • JPanel is good • To draw things: • extend JPanel • have the class override the paintComponent method • panel surface is transparent, so send drawing messages inside paintComponent to the graphic context • a Graphics2D object we'll reference with g2
Put something in a JPanel • Implement a JPanel class and draw a few strings • import java.awt.*; • publicclass DrawingPanel extends javax.swing.JPanel { • // Override the paintComponent method in JPanel • @Override • publicvoid paintComponent(Graphics g) { • g.drawString("Put this in g, which", 20, 20); • g.drawString("is in Panel", 20, 40); • g.drawString("which is in MyFrame", 20, 60); • } • }
Then add the JPanel to a JFrame to see the drawing • importjavax.swing.JFrame; • publicclassDrawOnAPanelextendsJFrame { • publicstaticvoid main(String[] args) { • newDrawOnAPanel().setVisible(true); • } • publicDrawOnAPanel() { • setTitle("A Frame with a panel"); • setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); • setSize(200, 120); • add(newDrawingPanel()); • } • }
The Graphics Object • paintComponent's Graphics g argument represents a "graphical context" object. • You can tell it to draw things on the panel • If you want another method to draw, pass the Graphics object to it—it like a canvas that understands draws • The actual object passed to every JPanel is a Graphics2D, so you can cast to Graphics2D • Never send paintcomponent messages • send repaint() messages instead
The Graphics Context • An object of the Graphics class represents a particular drawing surface • It defines a graphics context in which shapes will be rendered • Graphics is still around, but Java added an improved 2D Library in Java 1.3, use Graphics2D • Better drawing capabilities • It is analogous to using swing (JButton, JFrame) rather than older awt components (Button, Frame)
First cast Graphics to Graphics2D • // Override the paintComponent method in JPanel • @Override • publicvoidpaintComponent(Graphics g) { • // Graphics2D is a newer drawing context added after • // Graphics was around for a while. Graphics2D has • // more and better messages • Graphics2D g2 = (Graphics2D) g; • g2.drawString("Put this in g, which", 20, 20); • You can send messages to g2 such as drawString, draw(Shape), setColor, setBackground
Classes from java.awt.geom • The Rectangle2D.Double class (an inner class) • First 2 Arguments are the UPPER left corner • // Use the static Double inner class of Rectangle2D • // Floating point numbers are double by default • Rectangle2D body = // xcoord, ycoord, width, height • new Rectangle2D.Double(30.0, 70.0, 200.0, 50.0); • g2.draw(body);
draw Messages to Graphics2D • Can also draw any object that implements the Shape interface • public void draw(Shape s)Draws outline of the shape using this Graphics2D's current pen color • Shape leftWheel = // xcoord, ycoord, width, height • new Ellipse2D.Double(50.0, 100.0, 50.0, 50.0); • g2.draw(leftWheel); // 30.0, 70.0 is the upper left corner • You could also draw on a Graphics context with different messages • Recommended: use Graphics2D
Color • The Color class is used to define and manage the color in which shapes are drawn • Colors are defined by their RGB value, which defines the relative contribution of the primary colors red, green, and blue • The setPaint method of the Graphics2D defines the color used in future draw messages • g2.setPaint(aColor)
Color • The Color class contains several predefined colors, defined as public final static ints (class constants) • Many other colors can be defined using the constructor of the Color class • Over 16 million colors can be defined, but we cannot distinguish between that many • Color(int r, int g, int b) • Creates a color with the specified red, green, and blue values in range (0 - 255) • Furthermore, the hardware of most systems has limitations to the color options available
A Few Predefined Colors • You can create your own or use the constants in the Color class • Color.WHITE • Color.RED • Color.BLUE • Color.YELLOW • Color.PINK • Color.MAGENTA • Set future painting color like this • g2.setPaint(Color.BLUE);
fill • draw(shape) draws an outline of the shape • fill(shape) draws an outline of the shape and then fills it with whatever color is set • g2.setPaint(Color.GREEN); g2.setPaint(Color.BLUE); • g2.draw(body); g2.fill(body);
Fonts • A Font object is constructed with 3 arguments to indicate the • logical font names such as "SansSerif" • style such as Font.PLAIN and Font.BOLD • font size (10 is small, 30 is big) • Then send a setFont message to the Graphics2D object assume code shown on next slide is paintComponent
Drawing strings with Graphics2D • FontaFont=newFont("SansSerif",Font.BOLD,16); • g2.setFont(aFont); • g2.setPaint(Color.MAGENTA); • g2.drawString("A car with no top",45,180); • How would you draw a solid black wheel that can be seen?
Menus in Java • Needed in Noughts and Crosses
JMenus in Java Swing • Java menus use the Composite Design Pattern • JMenuBar is a composite extending Jcomponent • Can add others like JLabel, JTextField • Can also add JMenuItem to JMenuItem • JMenuItem has three subclasses • JMenu • JRadioButtonMenuItem • JCheckboxMenuItem
JMenu menu = new JMenu("Composite"); • menu.setMnemonic('C'); // Open with alt-C • // Create two leafs • JLabel label = new JLabel("Label"); • JTextField textF = new JTextField("text field"); • menu.add(label); • menu.add(textF); • // Add a Composite • JMenuItem menuItem = new JMenuItem("menu item"); • menu.add(menuItem); • // Add two Composites to a Composite • JMenu jmi1Nest = new JMenu("Nest 1"); • menu.add(jmi1Nest); • JMenuItem jmiNested1 = new JMenuItem("Nested in 1"); • jmi1Nest.add(jmiNested1); • JMenuItem jmiNested2 = new JMenuItem("Nested in 1 also"); • jmi1Nest.add(jmiNested2);
JMenuItemDemoComposite • // Add two more Composites • JMenuItem checkBox • = new JCheckBoxMenuItem("Human", false); • JMenuItem radioButton • = new JRadioButtonMenuItem("Computer", true); • menu.add(checkBox); • menu.add(radioButton); • // Add two more Composites • JMenuBar menuBar = new JMenuBar(); • setJMenuBar(menuBar); • menuBar.add(menu); • Run JMenuItemDemoComposite.java See code demo page
MouseListener • Do code demo
Drawing lines • import java.awt.Graphics; • import java.awt.Graphics2D; • import java.awt.event.MouseEvent; • import java.awt.event.MouseListener; • import javax.swing.JFrame; • import javax.swing.JPanel; • public class MousePanelWithMain extends JPanel { • public static void main(String[] args) { • JFrame window = new JFrame("Print where the moust clicked"); • window.setTitle("Listen to mouse events"); • window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); • window.setSize(300, 200); • window.add(new MousePanelWithMain()); • window.setVisible(true); • } • public MousePanelWithMain() { • this.addMouseListener(new ListenToMouse()); • } • // Override the paintComponent method in JPanel • @Override • public void paintComponent(Graphics g) { • super.paintComponent(g); • Graphics2D g2 = (Graphics2D) g; • g2.drawString("Click me and I print the x,y coordinate", 20, 20); • } • private class ListenToMouse implements MouseListener { • @Override • public void mouseClicked(MouseEvent mouseClick) { • System.out.println("Mouse click at " + mouseClick.getX() + " " + mouseClick.getY()); • } • @Override • public void mouseEntered(MouseEvent arg0) { • // TODO Auto-generated method stub • } • @Override • public void mouseExited(MouseEvent arg0) { • // TODO Auto-generated method stub • } • @Override • public void mousePressed(MouseEvent arg0) { • // TODO Auto-generated method stub • } • @Override • public void mouseReleased(MouseEvent arg0) { • // TODO Auto-generated method stub • } • } • }
So far… • We know how to subclass a JPanel and use a Graphics2D object as a drawing canvas inside the paintComponentmethod. • Sometimes we need to use an existing image rather than draw something ourselves
Drawing an Image • Java’s Image class in java.awt abstracts a bitmap image for use in drawing. • Images can be drawn to a panel through a Graphics object • An important Graphics2D method: • drawImage • But first…
How do we load an image? • java.awt contains a methodthat returns an image from a file on your disk • Image img = ImageIO.read(new File("fileName")); • Once we have an image and a graphics object, we can draw it • // some other drawing code • // 'g2' is a Graphics context object and img • // is an initialized Image. 12 is x, 24 is y pixels • g.drawImage(img, 12, 24, null);
Drawing Our Image • This code will draw img at the coordinates (12, 24) on the panel • The final ‘null’ is for an ImageObserver object, which we'll not need
Summary • To draw a jpg or gif image • Extend JPanel • Declare Image instance variables in that class • Let the constructor initialize • OveridepaintComponent • get a Graphics2D object named g2 perhaps • send drawImage messages to g2
Example code that needs6 jpg files in images • publicclass CardsOnTheWater extends JPanel { • private Image ocean, card1, card2, card3, card4, card5; • public CardsOnTheWater() { • try { • ocean = ImageIO.read(new File("images/ocean.jpg")); • card1 = ImageIO.read(new File("images/14h.jpg")); • card2 = ImageIO.read(new File("images/13h.jpg")); • card3 = ImageIO.read(new File("images/12h.jpg")); • card4 = ImageIO.read(new File("images/11h.jpg")); • card5 = ImageIO.read(new File("images/10h.jpg")); • } catch (IOException e) { • // TODO Auto-generated catch block • e.printStackTrace(); • } • }
This method is called when the panel needs to be redrawn • @Override • publicvoid paintComponent(Graphics g) { • Graphics2D g2 = (Graphics2D) g; • g2.drawImage(ocean, 0, 0, this); • g2.drawImage(card1, 10, 10, this); • g2.drawImage(card2, 30, 15, this); • g2.drawImage(card3, 50, 20, this); • g2.drawImage(card4, 70, 25, this); • g2.drawImage(card5, 90, 30, this); • }
Still need to Add JPanel to a JFrame • import javax.swing.JFrame; • import javax.swing.JPanel; • publicclass DrawCardsOnWaterMain extends JFrame { • publicstaticvoid main(String[] args) { • new DrawCardsOnWaterMain().setVisible(true); • } • public DrawCardsOnWaterMain() { • setSize(250, 250); • setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); • JPanel panel = new CardsOnTheWater(); • add(panel); • } • }