Graphics programming with java 2d
This presentation is the property of its rightful owner.
Sponsored Links
1 / 46

Graphics Programming with Java 2D PowerPoint PPT Presentation


  • 71 Views
  • Uploaded on
  • Presentation posted in: General

Graphics Programming with Java 2D. Java 2D API. S hapes, text, and images A uniform mechanism for performing transformations rotation and scaling, on objects. A wide array of presentation devices such as displays and printers, image formats and encodings, color spaces,

Download Presentation

Graphics Programming with Java 2D

An Image/Link below is provided (as is) to download presentation

Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author.While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server.


- - - - - - - - - - - - - - - - - - - - - - - - - - E N D - - - - - - - - - - - - - - - - - - - - - - - - - -

Presentation Transcript


Graphics programming with java 2d

Graphics Programming with Java 2D


Java 2d api

Java 2D API

  • Shapes, text, and images

  • A uniform mechanism for performing transformations

    • rotation and scaling, on objects.

  • A wide array of presentation devices such as

    • displays and printers,

    • image formats and encodings,

    • color spaces,

    • rendering techniques and effects.

  • Comprehensive textand font handling,

    • color support


Rendering

Rendering

  • The process of taking a collection of shapes, text, and images &

  • Figure out what colors the pixels should be on a screen or printer.

  • In the Java 2D API, the Graphics2D class is the rendering engine:

    • the Graphics2D object contains state attributes, such as color&

    • applies these attributes to the primitives when rendering them to various output devices.


The attributes of graphics2d object

The attributes of Graphics2D object

  • Paint:represents the color or pattern that the primitive will be when it is rendered.

  • Stroke: describes the line style of the outline of the shape

  • Font: the font of the text to be rendered

  • Rendering hint: suggests how a primitive should be rendered, such as whether a faster or more accurate algorithm should be used.

  • Transform: represents the mapping from user space to device space and additional graphic transforms, such as rotate and scale, to be applied to particular primitives.

  • Composite: defines how the overlapping parts of two graphic objects should be rendered

  • Clip: identifies the part of a primitive that is to be rendered


Graphics programming with java 2d

The Rendering Process


What is a rasterizer

What is a rasterizer?

  • Takes ideal shapes and produces coverage values for each pixel.

  • The coverage values represent how much of each pixel is covered by the shape.

  • These coverage values are called alpha values.

  • Each pixel has its own alpha value which indicates the transparency of the pixel


Is it possible to use native rasterizer

Is it possible to use native rasterizer?

  • Java 2D does not use a native rasterizer for rendering fonts

  • Uses the T2K font rasterizer from Type Solutions

    http://www.typesolutions.com/

  • By allowing T2K to rasterize fonts, the Java 2D API isn't dependent on native rasterizers for the scalable outline fonts that it supports

    • can result in more consistent metrics display across different platforms and between on-screen and off-screen rendering


The java 2d api classes

The Java 2D API classes

The classes that represent predetermined shapes.

Arc2D: an arc defined by a bounding rectangle, start angle, angular extent, and a closure type

CubicCurve2D:a cubic parametric curve segment.

Ellipse2D:an ellipse defined by a bounding rectangle.

Line2D:a line segment in (x, y) coordinate space.

Point2D: a location in (x,y) coordinate space.

QuadCurve2D:a quadratic parametric curve segment.

Rectangle2D: a rectangle defined by a location (x, y) and dimension (w x h)

RoundRectangle2D:a rectangle with rounded corners defined by a location (x, y), a dimension (w x h), and the width and height of the corner arc.


Defin ing odd shapes

Defining odd shapes

Two classes allow us to to define odd shapes

  • GeneralPath

    • Shapes must be created segment by segment,

    • We can combine straight lines and curved lines into a single shape.

  • Area

    • Supports constructive area geometry

    • allows us to combine two shapes to create another shape,

      • by adding or intersecting the shapes, subtracting one shape from another

      • by subtracting the intersection of the shapes.


  • Complex shapes from geometry primitives

    Complex Shapes from Geometry Primitives

    • Constructive Area Geometry (CAG) is the process of creating new geometric shapes by performing boolean operations on existing ones.

    • A special type of Shape called an Area supports boolean operations.

    • We can construct an Area from any Shape .


    Areas examples

    Areas examples

    • Areas support the following boolean operations:

      Union

      Subtraction

      Intersection

      Exclusive-or (XOR)


    Graphics programming with java 2d

    package untitled71;

    import javax.swing.UIManager;

    import java.awt.*;

    import java.awt.event.*;

    import java.awt.font.*;

    import java.awt.geom.*;

    import javax.swing.*;

    // This applet renders a pear, usingCAGmethods: add, intersect, and subtract.

    public class Pear extends JApplet {

    Ellipse2D.Double circle, oval, leaf, stem;

    Area circ, ov, leaf1, leaf2, st1, st2;

    public void init() {

    circle = new Ellipse2D.Double();

    oval = new Ellipse2D.Double();

    leaf = new Ellipse2D.Double();

    stem = new Ellipse2D.Double();

    circ = new Area(circle);

    ov = new Area(oval);

    leaf1 = new Area(leaf);

    leaf2 = new Area(leaf);

    st1 = new Area(stem);

    st2 = new Area(stem);

    setBackground(Color.white); }


    Graphics programming with java 2d

    public void paint (Graphics g) {

    Graphics2D g2 = (Graphics2D) g;

    Dimension d = getSize()

    int w = d.width;

    int h = d.height;

    double ew = w/2;

    double eh = h/2;

    g2.setColor(Color.green);

    // Creates the first leaf by filling the intersection of two Area objects created from an ellipse.

    leaf.setFrame(ew-16, eh-29, 15.0, 15.0);

    leaf1 = new Area(leaf);

    leaf.setFrame(ew-14, eh-47, 30.0, 30.0);

    leaf2 = new Area(leaf);

    leaf1.intersect(leaf2);

    g2.fill(leaf1);

    // Creates the second leaf.

    leaf.setFrame(ew+1, eh-29, 15.0, 15.0);

    leaf1 = new Area(leaf);

    leaf2.intersect(leaf1);

    g2.fill(leaf2);


    Graphics programming with java 2d

    g2.setColor(Color.black);

    /** Creates the stem by filling theArearesulting from the subtraction of twoAreaobjects created from an ellipse.**/

    stem.setFrame(ew, eh-42, 40.0, 40.0);

    st1 = new Area(stem);

    stem.setFrame(ew+3, eh-47, 50.0, 50.0);

    st2 = new Area(stem);

    st1.subtract(st2);

    g2.fill(st1);

    g2.setColor(Color.yellow);

    / ** Creates the pear itself by filling the Area resulting from the union of two Area objects created by two different ellipses **/

    circle.setFrame(ew-25, eh, 50.0, 50.0);

    oval.setFrame(ew-19, eh-20, 40.0, 70.0);

    circ = new Area(circle);

    ov = new Area(oval);

    circ.add(ov);

    g2.fill(circ);

    }


    Graphics programming with java 2d

    public static void main(String s[]) {

    JFrame f = new JFrame("Pear");

    f.addWindowListener(new WindowAdapter() {

    public void windowClosing(WindowEvent e)

    {System.exit(0);}

    });

    JApplet applet = new Pear();

    f.getContentPane(). add("Center", applet);

    applet.init();

    f.pack();

    f.setSize(new Dimension(150,200));

    f.show();

    }

    }


    Java awt font class diagrams

    java.awt.font.* Class Diagrams 

    • Font

      http://www.falkhausen.de/en/diagram/html/java.awt.font.Font.html

      Interfaces: MultipleMaster,OpenType

      Classes: java.awt.Font, FontRenderContext, LineMetrics, java.awt.FontMetrics

    • TextLayout

      http://www.falkhausen.de/en/diagram/html/java.awt.font.TextLayout.html

      Classes: TextHitInfo, TextLayout, TextLayout.CaretPolicy, LineBreakMeasurer, TextMeasurer

    • Attribute

      http://www.falkhausen.de/en/diagram/html/java.awt.font.Attribute.html

      Classes: java.text.AttributedCharacterIterator.Attribute, GraphicAttribute, ImageGraphicAttribute, TextAttribute, ShapeGraphicAttribute, NumericShaper, TransformAttribute

    • Glyph

      http://www.falkhausen.de/en/diagram/html/java.awt.font.Glyph.html

      Classes: GlyphMetrics, GlyphVector, GlyphJustificationInfo


    Java awt geom class diagrams

    java.awt.geom.* Class Diagrams

    • Shapes

      http://www.falkhausen.de/en/diagram/html/java.awt.geom.Shape.html

      Interfaces: java.awt.Shape

    • Lines

      http://www.falkhausen.de/en/diagram/html/java.awt.geom.LineShapes.html

      Interfaces: java.awt.Shape

      Classes:QuadCurve2D, QuadCurve2D.Double, QuadCurve2D.Float, CubicCurve2D, Line2D, CubicCurve2D.Double, Line2D.Double, CubicCurve2D.Float, Line2D.Float

    • Rects

      http://www.falkhausen.de/en/diagram/html/java.awt.geom.RectangleShapes.html

      Interfaces: java.awt.Shape

      Classes: RectangularShape, RoundRectangle2D.Float, RoundRectangle2D, RoundRectangle2D.Double,

      Ellipse2D.Double, Rectangle2D, Ellipse2D, Ellipse2D.Float,

      Arc2D, Arc2D.Float,

      java.awt.Rectangle, Rectangle2D.Float, Rectangle2D.Double, Arc2D.Double


    Java awt geom class diagrams cont d

    java.awt.geom.* Class Diagrams cont’d

    • Asym

      http://www.falkhausen.de/en/diagram/html/java.awt.geom.MiscShape.html

      Interfaces: java.awt.Shape

      Classes: GeneralPath, Area, java.awt.Polygon

    • Point

      http://www.falkhausen.de/en/diagram/html/java.awt.geom.Point.html

      Classes:Point2D, Dimension2D, java.awt.Insets, java.awt.Dimension, java.awt.Point, Point2D.Float, Point2D.Double

    • Misc

      http://www.falkhausen.de/en/diagram/html/java.awt.geom.Misc.html

      Interfaces: PathIterator

      Classes: AffineTransform, FlatteningPathIterator


    Java awt event class diagrams

    java.awt.event.* Class Diagrams

    • Listener

      http://www.falkhausen.de/en/diagram/html/java.awt.event.Listener.html

      Interfaces: java.util.EventListener, AWTEventListener, ActionListener, KeyListener, AdjustmentListener,ComponentListener, MouseWheelListener, ContainerListener, MouseListener, FocusListener, MouseMotionListener, HierarchyBoundsListener, WindowStateListener, HierarchyListener, WindowFocusListener, InputMethodListener, WindowListener, ItemListener, TextListener

      Classes: java.util.EventListenerProxy, AWTEventListenerProxy, KeyAdapter, ComponentAdapter,ContainerAdapter, MouseAdapter, FocusAdapter, MouseMotionAdapter, HierarchyBoundsAdapter, WindowAdapter

    • Events

      http://www.falkhausen.de/en/diagram/html/java.awt.event.Events.html

      Interfaces: java.awt.ActiveEvent

      Classes: InputMethodEvent, java.awt.AWTEvent, java.util.EventObject, HierarchyEvent,InvocationEvent, TextEvent, ActionEvent, ItemEvent, AdjustmentEvent, ComponentEvent, PaintEvent,FocusEvent, InputEvent, WindowEvent, ContainerEvent, MouseEvent, KeyEvent, MouseWheelEvent,java.awt.AWTKeyStroke, javax.swing.KeyStroke


    Java awt event class diagram cont d

    java.awt.event.* Class Diagram cont’d

    • Support

      http://www.falkhausen.de/en/diagram/html/java.awt.event.EventSupport.html

      Classes: java.awt.AWTEventMulticaster, java.awt.EventQueue


    Java x swing class diagrams

    javax.swing.* Class Diagrams

    • Components

      • Hierarchy

      • JComponent

      • Labels

      • Slider+Progress

      • Spinner

      • CellEditor

      • CellRenderer

      • Container

      • RootpaneContainer

      • Panes

      • Scrolling

      • Layers

        Classes: javax.swing.JComponent


    Java x swing class diagrams cont d

    javax.swing.* Class Diagrams cont’d

    • Container

      • RootpaneContainer

      • Panes

      • Scrolling

      • Layers

  • Dialogs

    • JOptionPane

    • JFileChooser

    • JColorChooser


  • Java x swing class diagrams cont d1

    javax.swing.* Class Diagrams cont’d

    • Button+Menu

      • Buttons

      • ButtonModel

      • MenuSupport

      • MenuEvents

      • Lists

      • List+Combo

      • ListModel

      • ListEvent

  • Lists

    • List+Combo

    • ListModel

    • ListEvent


  • Java x swing class diagrams cont d2

    javax.swing.* Class Diagrams cont’d

    • Action

    • LookAndFeel

    • Utilities

    • Exceptions

    • javax.swing.border

    • javax.swing.event

      • Listener

      • Events

    • javax.swing.plaf

      • ComponentUI

      • UIResource

    • javax.swing.table

      • JTable

      • TableModel

      • Support

      • Events


    Java x swing class diagrams cont d3

    javax.swing.* Class Diagrams cont’d

    • javax.swing.text

      • TextComponents

      • Formatter

      • Document

      • EditorKit

      • AttributeSet

      • View

      • Element

      • Position

      • Caret

      • AbstractWriter

      • Utilities

      • Events


    Java x swing class diagrams cont d4

    javax.swing.* Class Diagrams cont’d

    • javax.swing.text.html

      • HTMLDocument

      • HTMLEditorKit

      • StyleSheet

      • Views

      • HTML

      • Parsing

      • javax.swing.text.html.parser

  • javax.swing.tree

    • JTree

    • TreeModel

    • TreeNode

    • Events

  • javax.swing.undo

    http://www.falkhausen.de/en/diagram/spec/javax.swing.html


  • General approach to java 2d api

    General Approach to JAVA 2D API

    • Transition from the Graphics object to a Graphics2D object

      public void paintComponent(Graphics g) {

      super.paintComponent(g);

      // Typical Swing approach

      Graphics2D g2d = (Graphics2D)g;

      g2d.doSomeWork(...);

      ... }

    • Create a Shape object

      Rectangle2D.Double rect = ...;

      Ellipse2D.Double ellipse = ...;

      Polygon poly = ...;

      GeneralPath path = ...;

      SomeShapeYouDefined shape = ...;

      // Satisfies Shape interface ...


    General approach to java 2d api cont d

    General Approach to JAVA 2D API cont’d

    • Optional: modify drawing parameters

      g2d.setPaint(fillColorOrPattern);

      g2d.setStroke(penThicknessOrPattern);

      g2d.setComposite(someAlphaComposite);

      g2d.setFont(someFont);

      g2d.translate(...);

      g2d.rotate(...);

      g2d.scale(...);

      g2d.shear(...);

      g2d.setTransform(someAffineTransform);

    • Draw an outlined or solid version of the Shape

      g2d.draw(someShape);

      g2d.fill(someShape);


    Example drawing shapes

    Example: Drawing Shapes

    import javax.swing.*; // For JPanel

    import java.awt.*; // For Graphics

    import java.awt.geom.*; // For Ellipse2D

    public class ShapeExample extends JPanel {

    private Ellipse2D.Double circle = new Ellipse2D.Double(10, 10, 350, 350);

    private Rectangle2D.Double square = new Rectangle2D.Double(10, 10, 350, 350);

    public void paintComponent(Graphics g) {

    clear(g);

    Graphics2D g2d = (Graphics2D)g;

    g2d.fill(circle);

    g2d.draw(square); }

    // super.paintComponent clears offscreen pixmap,we're using double buffering by default

    protected void clear(Graphics g) {

    super.paintComponent(g); }

    protected Ellipse2D.Double getCircle() {

    return(circle); }

    public static void main(String[] args) {

    WindowUtilities.openInJFrame(new ShapeExample(), 380, 400); } }


    Windowutilities java utility class that simplifies creating a window and setting the look and feel

    WindowUtilities.javaUtility class that simplifies creating a window and setting the look and feel.

    import javax.swing.*

    ; import java.awt.*;

    public class WindowUtilities {

    /** Tell system to use native look and feel, as in previous * releases. Metal

    (Java) LAF is the default otherwise. **/

    public static voidsetNativeLookAndFeel(){

    try {

    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());

    }

    catch(Exception e) {

    System.out.println("Error setting native LAF: " + e);

    }

    }

    /** A simplified way to see a JPanel or other Container.

    * Pops up a JFrame with specified Container as the content pane.

    */

    public static JFrame openInJFrame(Container content, int width, int height, String title,

    Color bgColor) {

    JFrame frame = new JFrame(title);


    Graphics programming with java 2d

    frame.setBackground(bgColor);

    content.setBackground(bgColor);

    frame.setSize(width, height);

    frame.setContentPane(content);

    frame.addWindowListener(new ExitListener());

    frame.setVisible(true);

    return(frame);

    }

    /** Uses Color.white as the background color.

    public static JFrame openInJFrame(Container content, int width,

    int height, String title)

    {

    return(openInJFrame(content, width, height, title, Color.white));

    }

    /** Uses Color. white as the background color, and the

    * name of the Container's class as the JFrame title. */

    public static JFrame openInJFrame(Container content, int width, int height) { return(openInJFrame(content, width, height,content.getClass().getName(),

    Color.white));

    } }


    Exitlistener java a windowlistener with support to close the window

    ExitListener.javaA WindowListener with support to close the window

    import java.awt.*;

    import java.awt.event.*;

    public class ExitListener extends WindowAdapter {

    public void windowClosing(WindowEvent event) {

    System.exit(0);

    }

    }


    Paint attribute of the graphics2d f ill ing a shape

    Paint attribute of the Graphics2DFilling a Shape

    • AColor (solid color): Color.red, Color.yellow

    • AGradientPaint (gradient fill gradually combining two colors)

      Constructors takes two points, two colors, and optionally a boolean flag that indicates that the color pattern should cycle.

    • A TexturePaint (tiled image), or

    • A new version of Paint that we write ourselves

    • Use setPaintand getPaint to change and retrieve the Paint settings.

      • setPaint and getPaint supersede the setColor and getColor methods in Graphics.


    Example gradient fills

    Example: Gradient Fills

    import java.awt.*;

    public class GradientPaintExample extends ShapeExample

    { // Red at (0,0), yellow at (175,175), changes gradually between.

    private GradientPaint gradient = new GradientPaint(0, 0, Color.red,

    175, 175, Color.yellow, true);

    // true means to repeat pattern

    public void paintComponent(Graphics g) {

    clear(g);

    Graphics2D g2d = (Graphics2D)g;

    drawGradientCircle(g2d);

    }

    protected void drawGradientCircle(Graphics2D g2d) {

    g2d.setPaint(gradient);

    g2d.fill(getCircle());

    g2d.setPaint(Color.black);

    g2d.draw(getCircle()); }

    public static void main(String[] args) {

    WindowUtilities.openInJFrame(new GradientPaintExample(), 380, 400); } }


    Graphics programming with java 2d

    Stroke AttributesEach of the shapes drawn by the applet is constructed from one of the geometries and is then rendered through Graphics2D.

    The rectHeight and rectWidth variables define the dimensions of the space

    where each shape is drawn, in pixels. The xandyvariables change for each

    shape so that they are drawn in a grid formation.

    //draw Line2D.Double

    g2.draw(new Line2D.Double(x, y+rectHeight-1, x + rectWidth, y));

    g2.drawString("Line2D", x, stringY);

    // draw Rectangle2D.Double

    g2.setStroke(stroke);

    g2.draw(new Rectangle2D.Double(x, y, rectWidth, rectHeight));

    g2.drawString("Rectangle2D", x, stringY);

    // draw RoundRectangle2D.Double

    g2.setStroke(dashed);

    g2.draw(new RoundRectangle2D.Double(x, y, rectWidth, rectHeight, 10, 10)

    g2.drawString("RoundRectangle2D", x, stringY);


    Stroke attributes cont d

    Stroke Attributes cont’d

    // draw Arc2D.Double

    g2.setStroke(wideStroke);

    g2.draw(new Arc2D.Double(x, y, rectWidth, rectHeight, 90, 135,

    Arc2D.OPEN));

    // draw Ellipse2D.Double

    g2.setStroke(stroke);

    g2.draw(new Ellipse2D.Double(x, y, rectWidth, rectHeight));


    Draw ing generalpath polygon

    Drawing GeneralPath (polygon)

    int x1Points[] = {x, x+rectWidth, x, x+rectWidth};

    int y1Points[] = {y, y+rectHeight, y+rectHeight, y};

    GeneralPath polygon = new

    GeneralPath(GeneralPath.WIND_EVEN_ODD,

    x1Points.length);

    polygon.moveTo(x1Points[0], y1Points[0]);

    for (int index = 1; index < x1Points.length; index++)

    {

    polygon.lineTo(x1Points[index], y1Points[index]);

    };

    polygon.closePath();

    g2.draw(polygon);


    D raw ing generalpath polyline

    Drawing GeneralPath (polyline)

    int x2Points[] = {x, x+rectWidth, x, x+rectWidth};

    int y2Points[] = {y, y+rectHeight, y+rectHeight, y};

    GeneralPath polyline = new

    GeneralPath(GeneralPath.WIND_EVEN_ODD,

    x2Points.length);

    polyline.moveTo (x2Points[0], y2Points[0]);

    for (int index = 1; index < x2Points.length; index++) {

    polyline.lineTo(x2Points[index], y2Points[index]);

    };

    g2.draw(polyline);


    Stroke attributes cont d1

    Stroke Attributes cont’d

    // fill Rectangle2D.Double (red)

    g2.setPaint(red);

    g2.fill(new Rectangle2D.Double(x, y, rectWidth,rectHeight));

    // fill RoundRectangle2D.Double

    g2.setPaint(redtowhite);

    g2.fill(new RoundRectangle2D.Double(x, y, rectWidth, rectHeight,

    10, 10));

    // fill Arc2D g2.setPaint(red);

    g2.fill(new Arc2D.Double(x, y, rectWidth, rectHeight, 90, 135,

    Arc2D.OPEN));


    Us ing the java 2d apis to define and render the g raphics and t ext

    Using the Java 2D APIs to define and render the Graphics and Text

    public class ShapesDemo2D extends JApplet {

    final static int maxCharHeight = 15;

    final static int minFontSize = 6;

    final static Color bg = Color.white;

    final static Color fg = Color.black;

    final static Color red = Color.red;

    final static Color white = Color.white;

    final static BasicStroke stroke = new BasicStroke(2.0f);

    final static BasicStroke wide Stroke = new BasicStroke(8.0f);

    final static float dash1[] = {10.0f}

    final static BasicStroke dashed = new BasicStroke(1.0f,

    BasicStroke.CAP_BUTT,BasicStroke.JOIN_MITER,

    10.0f, dash1, 0.0f);


    Graphics programming with java 2d

    Dimension totalSize;

    FontMetrics fontMetrics;

    public void init() {

    //Initialize drawing colors

    setBackground(bg);

    setForeground(fg);

    }

    FontMetrics pickFont(Graphics2D g2,

    String longString,

    int xSpace) {

    boolean fontFits = false;

    Font font = g2.getFont();

    FontMetrics fontMetrics = g2.getFontMetrics();

    int size = font.getSize();

    String name = font.getName();

    int style = font.getStyle();


    Graphics programming with java 2d

    while ( !fontFits )

    if ( (fontMetrics.getHeight() <= maxCharHeight)

    && (fontMetrics.stringWidth(longString) <= xSpace) ) {

    fontFits = true;

    }

    else {

    if ( size <= minFontSize ) {

    fontFits = true;

    }

    else {

    g2.setFont(font = new Font name, style, --size));

    fontMetrics = g2.getFontMetrics();

    } } }

    return fontMetrics;

    }


    Graphics programming with java 2d

    public void paint(Graphics g) {

    Graphics2D g2 = (Graphics2D) g;

    g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,

    RenderingHints.VALUE_ANTIALIAS_ON);

    Dimension d = getSize();

    int gridWidth = d.width / 6;

    int gridHeight = d.height / 2;

    fontMetrics = pickFont(g2, "Filled and Stroked GeneralPath", gridWidth);

    Color fg3D = Color.lightGray;

    g2.setPaint(fg3D);

    g2.draw3DRect(0, 0, d.width - 1, d.height - 1, true);

    g2.draw3DRect(3, 3, d.width - 7, d.height - 7, false);

    g2.setPaint(fg);

    int x = 5;

    int y = 7;

    int rectWidth = gridWidth - 2*x;

    int stringY = gridHeight - 3 - fontMetrics.getDescent();

    int rectHeight = stringY - fontMetrics.getMaxAscent() - y - 2;


  • Login