如何在我要绘制的形状内插入文本 Java

How to insert text inside a shape that i will draw in Java

所以我想在形状中插入文本。该形状将由用户绘制,例如矩形。释放鼠标时,会发送一条弹出消息 "Enter name:"。用户输入矩形的名称,然后它直接出现在形状矩形内。

你能指导我实现这个目标吗?这样做的正确方法是什么? 我已经有了我的代码块,我可以在其中绘制矩形并发送弹出消息,但我不知道如何放置 "text inside the shape"

这是绘制形状的用户界面。

import java.awt.AlphaComposite;
import java.awt.BasicStroke;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.RenderingHints;
import java.awt.Shape;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionAdapter;
import java.awt.geom.Ellipse2D;
import java.awt.geom.Line2D;
import java.awt.geom.Rectangle2D;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.Scanner;

import javax.imageio.ImageIO;
import javax.swing.Box;
import javax.swing.Icon;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JColorChooser;
import javax.swing.JComponent;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JSeparator;
import javax.swing.JSlider;
import javax.swing.JTextField;
import javax.swing.SwingConstants;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import javax.swing.filechooser.FileNameExtensionFilter;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.WindowConstants;

public class Lesson49_1 extends JFrame {
    private int c;
    
    public int getC() {
    return c;
}
public void setC(int c) {
    this.c= this.c;
}

    private static final long serialVersionUID = -140274271716086522L;

    JMenuBar menubar;
    JMenu File, Exit;
    JMenuItem New, Open;
    JComponent DrawingBoard;
    Font textFont;
    String text;
    Color textColor;
    {
        
        textColor = new Color(0x404000);
        
       text = "Hello, World!";
        
    }

    JButton  lineBut, ellipseBut, rectBut, strokeBut;

    DecimalFormat dec = new DecimalFormat("#.##");

    // Contains all of the rules for drawing

    Graphics2D graphSettings;

   
    // Going to be used to monitor what shape to draw next

    int currentAction = 1;
    

    // Transparency of the shape

    // Default stroke and fill colors

    Color strokeColor = Color.BLACK;

    public static void main(String[] args) {
        new Lesson49_1();
    }
    
    
    
    
    public Lesson49_1() {
        // Define the defaults for the JFrame
        
        this.setSize(800, 600);
        this.setTitle("ERD BUILDER");
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        this.setJMenuBar(menubar);

        JMenuBar menuBar = new JMenuBar();

        // Add the menubar to the frame
        setJMenuBar(menuBar);

        // Define and add two drop down menu to the menubar
        JMenu fileMenu = new JMenu("File");
        JMenu editMenu = new JMenu("Edit");
        JMenu dbMenu = new JMenu("Database");
        JMenu ToolsMenu = new JMenu("Tools");
        JMenu HelpMenu = new JMenu("Help");
        menuBar.add(fileMenu);
        menuBar.add(editMenu);
        menuBar.add(dbMenu);
        menuBar.add(ToolsMenu);
        menuBar.add(HelpMenu);
        // Create and add simple menu item to one of the drop down menu
        JMenuItem newAction = new JMenuItem("New Project");
        JMenuItem openAction = new JMenuItem("Open File");
        JMenuItem exitAction = new JMenuItem("Quit");
        JMenuItem cutAction = new JMenuItem("Cut");
        JMenuItem copyAction = new JMenuItem("Copy");
        JMenuItem pasteAction = new JMenuItem("Paste");
        JMenuItem UndoAction = new JMenuItem("Undo");
        JMenuItem RedoAction = new JMenuItem("Redo");
        JMenuItem clearAction = new JMenuItem("Clear");
        JMenuItem saveAction = new JMenuItem("Save");
        JMenuItem exportAction = new JMenuItem("Export");
        JMenuItem printAction = new JMenuItem("Print");
        JMenuItem ConvertAction = new JMenuItem("Convert To Tables");
        JMenuItem ColorAction = new JMenuItem("Color Picker");
        JMenuItem ZoomAction = new JMenuItem("Zoom");
        JMenuItem EntityAction = new JMenuItem("Entity & Attributes");
        JMenuItem RelationshipAction = new JMenuItem("Relationship Attributes");
        JMenuItem HelpAction = new JMenuItem("Help");
        JMenuItem AboutAction = new JMenuItem("About");

        fileMenu.add(newAction);
        fileMenu.addSeparator();
        fileMenu.add(openAction);
        fileMenu.addSeparator();
        fileMenu.add(saveAction);
        fileMenu.addSeparator();
        fileMenu.add(exportAction);
        fileMenu.addSeparator();
        fileMenu.add(printAction);
        fileMenu.addSeparator();
        fileMenu.add(exitAction);

        editMenu.add(UndoAction);
        editMenu.addSeparator();
        editMenu.add(RedoAction);
        editMenu.addSeparator();
        editMenu.add(cutAction);
        editMenu.addSeparator();
        editMenu.add(copyAction);
        editMenu.addSeparator();
        editMenu.add(pasteAction);
        editMenu.addSeparator();
        editMenu.add(clearAction);

        dbMenu.add(ConvertAction);

        ToolsMenu.add(ColorAction);
        ToolsMenu.addSeparator();
        ToolsMenu.add(ZoomAction);
        ToolsMenu.addSeparator();
        ToolsMenu.add(EntityAction);
        ToolsMenu.addSeparator();
        ToolsMenu.add(RelationshipAction);

        HelpMenu.add(HelpAction);
        HelpMenu.addSeparator();
        HelpMenu.add(AboutAction);
        
        
        exitAction.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent arg0) {
               
        }}
        );
        
        
        
        
        
        
        ConvertAction.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent arg0) {
                
               //new ConvertForm().setVisible(true);
                
                
               
        }}
        );
        
        
        

        newAction.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent arg0) {

                new Lesson49_1().setVisible(true);
            }
        });
        
        

        JPanel buttonPanel = new JPanel();
       
        JPanel FieldPanel = new JPanel();

        // Swing box that will hold all the buttons

        Box theBox = Box.createVerticalBox();
        Box theBoxs = Box.createVerticalBox();

        // Make all the buttons in makeMeButtons by passing the
        // button icon.

        
        lineBut = makeMeButtons("./src/line.png", 2);
        ellipseBut = makeMeButtons("./src/ellipse.png", 3);
        rectBut = makeMeButtons("./src/rectangle.png", 4);

        // Make all the buttons in makeMeColorButton by passing the
        // button icon and true for stroke color or false for fill

        strokeBut = makeMeColorButton("./src/stroke.png", 5, true);


        // Add the fields to the boxs

        

        //theBox.add(brushBut);
        theBox.add(lineBut);
        theBox.add(ellipseBut);
        theBox.add(rectBut);
        theBox.add(strokeBut);
       
        buttonPanel.add(theBox);
        FieldPanel.add(theBoxs);
        

        this.add(buttonPanel, BorderLayout.WEST);
        this.add(FieldPanel, BorderLayout.EAST);
        buttonPanel.setPreferredSize(new Dimension(200,480));        
        FieldPanel.setPreferredSize(new Dimension(200,480));
        // Make the drawing area take up the rest of the frame

        // this.add(new DrawingBoard(), BorderLayout.CENTER);
        final DrawingBoard drawPanel = new DrawingBoard();
        this.add(drawPanel, BorderLayout.CENTER);
        this.getContentPane().setBackground(Color.WHITE);

        
        
        
        
        
        exportAction.addActionListener(new ActionListener() {

            public void actionPerformed(ActionEvent arg0) {
                BufferedImage image = new BufferedImage(drawPanel.getWidth(),
                        drawPanel.getHeight(), BufferedImage.TYPE_INT_ARGB);
                Graphics2D g = image.createGraphics();
                drawPanel.paint(g);
                g.dispose();

                JFileChooser fileChooser = new JFileChooser();
                File theDirectory = new File("C:/Users/Wenda/Desktop");
                fileChooser.setCurrentDirectory(theDirectory);
                FileNameExtensionFilter pngFilter = new FileNameExtensionFilter(
                        "PNG file (*.png)", "png");
                fileChooser.addChoosableFileFilter(pngFilter);
                fileChooser.setFileFilter(pngFilter);

                int status = fileChooser.showSaveDialog(Lesson49_1.this);

                if (status == JFileChooser.APPROVE_OPTION) {
                    try {
                        ImageIO.write(image, "png",
                                fileChooser.getSelectedFile());
                        JOptionPane.showMessageDialog(null, "Image saved to "
                                + fileChooser.getSelectedFile().getName());
                    } catch (Exception ex) {
                        ex.printStackTrace();
                    }
                }
            }
        });
        // Show the frame
        this.setVisible(true);
    }

    public JButton makeMeButtons(String iconFile, final int actionNum) {
        JButton theBut = new JButton();
        Icon butIcon = new ImageIcon(iconFile);
        theBut.setIcon(butIcon);

         theBut.addActionListener(new ActionListener() {

            public void actionPerformed(ActionEvent e) {
                currentAction = actionNum;
            }
        });
        return theBut;
    }

    // Spits out buttons based on the image supplied and
    // whether a stroke or fill is to be defined

    public JButton makeMeColorButton(String iconFile, final int actionNum,
            final boolean stroke) {
        JButton theBut = new JButton();
        Icon butIcon = new ImageIcon(iconFile);
        theBut.setIcon(butIcon);

        theBut.addActionListener(new ActionListener() {

            public void actionPerformed(ActionEvent e) {

                if (stroke) {

                    // JColorChooser is a popup that lets you pick a color

                    strokeColor = JColorChooser.showDialog(null,
                            "Pick a Stroke", Color.BLACK);
                } else {
                                    }
            }
        });

        return theBut;
    }
    public class DrawingBoard extends JComponent {
        Font textFont = new Font("Arial", Font.BOLD, 12);

        private static final long serialVersionUID = -4431176095451940075L;

        // ArrayLists that contain each shape drawn along with
        // that shapes stroke and fill
        ArrayList<Shape> shapes = new ArrayList<Shape>();
        ArrayList<Color> shapeStroke = new ArrayList<Color>();
        ArrayList<Integer> count = new ArrayList<Integer>();
        
        
        Point drawStart, drawEnd;
        // Monitors events on the drawing area of the frame

        public DrawingBoard() {
                      

            this.addMouseListener(new MouseAdapter() {

                public void mousePressed(MouseEvent e) {

                    if (currentAction != 1) {

                        // When the mouse is pressed get x & y position

                        drawStart = new Point(e.getX(), e.getY());
                        drawEnd = drawStart;
                        repaint();
                    }
                }
            
                public void mouseReleased(MouseEvent e) {
                    int counts =0;
                    if (currentAction != 1) {
                        Shape aShape = null;
                        
                        if (currentAction == 2) {
                            aShape = drawLine(drawStart.x, drawStart.y,
                            e.getX(), e.getY());
                            shapes.add(aShape);
                            shapeStroke.add(strokeColor);
                            drawStart = null;
                            drawEnd = null;
                            repaint();
                        } else

                        if (currentAction == 3) {
                            aShape = drawEllipse(drawStart.x, drawStart.y,
                             e.getX(), e.getY());
                            shapes.add(aShape);
                            shapeStroke.add(strokeColor);
                            drawStart = null;
                            drawEnd = null;                                                        
                            repaint();
                            counts = counts+1;
                            count.add(counts);
                            int sizes = count.size();
                            System.out.println(sizes);
//                            new AttributeForm().setVisible(true);
                        } else

                        if (currentAction == 4) {
                            //draw the rectangle
                            aShape = drawRectangle(drawStart.x, drawStart.y,
                            e.getX(), e.getY());
                            shapes.add(aShape);
                            shapeStroke.add(strokeColor);
                            drawStart = null;
                            drawEnd = null;
                            
                            
                            String text = (String) JOptionPane.showInputDialog(DrawingBoard, "Enter name:");
                            while (text == null || text.isEmpty()) {
                                    text = (String) JOptionPane.showInputDialog(DrawingBoard, "You must enter a valid name!  Please try again:");
                                                                    
                            }
                             repaint();      
                                    


    

                          //new EntityForm().setVisible(true);
                        }

                        // Add shapes, fills and colors to there ArrayLists

                                              

                    }

                }
            });
            
              this.addMouseListener(new MouseAdapter() {
            @Override
            public void mouseClicked(MouseEvent me) {
                JTextField name = new JTextField(15);
                super.mouseClicked(me);
                for (Shape s : shapes) {

                    if (s.contains(me.getPoint())) {//check if mouse is clicked within shape

                        //we can either just print out the object class name
                        System.out.println("Clicked a "+s.getClass().getName());

                        //or check the shape class we are dealing with using instance of with nested if
                        if (s instanceof Rectangle2D) {
                            
                            //create table  
                            
                        } 
                         else if (s instanceof Ellipse2D) {
                            
                           
                             
                            
                            
                            
                        }

                    }
                }
            }
        });

            this.addMouseMotionListener(new MouseMotionAdapter() {

                public void mouseDragged(MouseEvent e) {

                    // If this is a brush have shapes go on the screen quickly

                    if (currentAction == 1) {

                        int x = e.getX();
                        int y = e.getY();

                        Shape aShape = null;
                        shapes.add(aShape);

                        shapeStroke.add(strokeColor);

                        // Add the transparency value
                    }

                    // Get the final x & y position after the mouse is dragged

                    drawEnd = new Point(e.getX(), e.getY());
                    repaint();
                }
            });
        }

        public void paint(Graphics g) {
            
            final int width = getWidth();
        final int height = getHeight();
             final double size = Math.sqrt(width * height);
            // Class used to define the shapes to be drawn

            graphSettings = (Graphics2D) g;
            

            // Antialiasing cleans up the jagged lines and defines rendering
            // rules

            graphSettings.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
                    RenderingHints.VALUE_ANTIALIAS_ON);

            // Defines the line width of the stroke

            graphSettings.setStroke(new BasicStroke(4));

            // Iterators created to cycle through strokes and fills
            Iterator<Color> strokeCounter = shapeStroke.iterator();
            for (Shape s : shapes) {
 
                // Grabs the next stroke from the color arraylist
                graphSettings.setPaint(strokeCounter.next());

                graphSettings.draw(s);

            }

            // Guide shape used for drawing
            if (drawStart != null && drawEnd != null) {
                // Makes the guide shape transparent

                graphSettings.setComposite(AlphaComposite.getInstance(
                        AlphaComposite.SRC_OVER, 0.40f));

                // Make guide shape gray for professional look

                graphSettings.setPaint(Color.LIGHT_GRAY);

                Shape aShape = null;

                if (currentAction == 2) {
                    aShape = drawLine(drawStart.x, drawStart.y, drawEnd.x,
                            drawEnd.y);
                } else

                if (currentAction == 3) {
                    aShape = drawEllipse(drawStart.x, drawStart.y, drawEnd.x,
                            drawEnd.y);
                } else

                if (currentAction == 4) {
                    

                    // Create a new rectangle using x & y coordinates

                    aShape = drawRectangle(drawStart.x, drawStart.y, drawEnd.x,
                            drawEnd.y);  
                    //Add text inside the rectangle
                    
                    g.setColor(Color.black);
        Font textFont = this.textFont.deriveFont((float) size * (1 / 12f));
        g.setFont(textFont);
        FontMetrics textMetrics = g.getFontMetrics();
        g.drawString(text, (width - textMetrics.stringWidth(text)) / 2, (textMetrics.getAscent() + (height - (textMetrics.getAscent() + textMetrics.getDescent())) / 2));
                    
                    
                    FontMetrics fm = g.getFontMetrics();
                                int fontAscent = fm.getAscent();                                
                                int stringX = Math.min(drawStart.x, drawEnd.x);
                                int stringY = Math.min(drawStart.y, drawEnd.y) + fontAscent;
                                g.drawString(text, stringX,  stringY);

                }

                graphSettings.draw(aShape);
            }
        }

    
        private Rectangle2D.Float drawRectangle(int x1, int y1, int x2, int y2) {
            // Get the top left hand corner for the shape
            // Math.min returns the points closest to 0

            int x = Math.min(x1, x2);
            int y = Math.min(y1, y2);

            // Gets the difference between the coordinates and

            int width = Math.abs(x1 - x2);
            int height = Math.abs(y1 - y2);

            return new Rectangle2D.Float(x, y, width, height);
        }

           private Ellipse2D.Float drawEllipse(int x1, int y1, int x2, int y2) {
            int x = Math.min(x1, x2);
            int y = Math.min(y1, y2);
            int width = Math.abs(x1 - x2);
            int height = Math.abs(y1 - y2);

            return new Ellipse2D.Float(x, y, width, height);
        }

        private Line2D.Float drawLine(int x1, int y1, int x2, int y2) {

            return new Line2D.Float(x1, y1, x2, y2);
        }
        
       public void drawString(String text,int stringX, int stringY){
        }
        
           }
    
    }
    

EntityForm 是获取矩形名称的窗体。这是一个简单的形式 "Enter name:"

"CODE EDITED(3)"

试试这个:

  public class MyCanvas extends JPanel {
    public static void main(String[] args) {
        JFrame frame = new JFrame();
        frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        frame.setLayout(new BorderLayout());
        frame.getContentPane().add(new MyCanvas(), BorderLayout.CENTER);
        frame.setSize(400, 400);
        frame.setMinimumSize(frame.getSize());
        frame.pack();
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    }


    Color rectColor;
    Color textColor;
    Font textFont;
    String text;

    {
        rectColor = new Color(0x0060FF);
        textColor = new Color(0x404000);
        textFont = new Font("Arial", Font.BOLD, 12);
        text = "Hello, World!";
    }

    @Override
    public void paint(Graphics g) {
        final int width = getWidth();
        final int height = getHeight();
        final double size = Math.sqrt(width * height);

        //setup
        Graphics2D g2 = (Graphics2D) g;
        g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);

        //rectangle
        g.clearRect(0, 0, width, height);
        g.setColor(Color.blue);
        int s = (int) (size * (1 / 10d));
        g.fillRoundRect(0, 0, width, height, s, s);

        //text
        g.setColor(Color.black);
        Font textFont = this.textFont.deriveFont((float) size * (1 / 12f));
        g.setFont(textFont);
        FontMetrics textMetrics = g.getFontMetrics();
        g.drawString(text, (width - textMetrics.stringWidth(text)) / 2, (textMetrics.getAscent() + (height - (textMetrics.getAscent() + textMetrics.getDescent())) / 2));
    }
}

所以你有两个问题:

  1. 如何获取用户输入的文本
  2. 如何在矩形中绘制文本

获取文本

您的 EntityForm class 应该有某种访问器方法来获取文本字段本身或文本字段的值(即用户输入的文本)。

我假设它还有一个 "Okay" 按钮供用户在输入文本后单击?因此,您需要先保存对新 EntityForm 的引用,然后将事件处理程序添加到 "okay" 按钮,然后再将其设置为可见。

因此,例如:

final EntityForm ef = new EntityForm();
ef.getOkayButton().addActionListener(new ActionListener(){
    public void actionPerformed(ActionEvent e) {

        String text = ef.getTextInput().getText();
        // draw text code here...

    }
});
ef.setVisible(true);

以上显然只是一个示例,因为我不知道 EntityForm class 的 API,但它应该足以让您继续。如果您需要更具体的答案,那么您还需要 post EntityForm 的代码。

但是,比使用 EntityForm class 更简单的选择是使用内置的 JOptionPane.showInputDialog() 方法。因此,您可以这样做,而不是调用 new EntityForm()

String text = (String) JOptionPane.showInputDialog(drawingBoard, "Enter name:");
// Note that if the user presses "cancel" then text will be null.  Also, 
// user may not have entered any text and pressed "okay", so text will be
// an empty string.
if (text == null || text.isEmpty()) {
    text = "[unnamed]";
}
// Instead of substituting for an alternative string, you could show 
// an error message and ask the user for a name again until a valid
// name is supplied.e.g.:
/*
while (text == null || text.isEmpty()) {
    text = (String) JOptionPane.showInputDialog(drawingBoard, "You must enter a valid name!  Please try again:");
}
*/

// draw text code here...

绘制文本

此处需要Graphics2d#drawString() 方法之一。查看 API 文档以获取更多详细信息和选项,但其要点是:

// get the size of the current font
FontMetrics fm = g.getFontMetrics();
int fontAscent = fm.getAscent();

// drawString co-ordinates specify the baseline of the text, so lets 
// tell it to draw at fontAscent pixels below the top of the rectangle.
// Note that the user might have started dragging from any corner of the 
// rectangle, so we need to determine which co-ordinates represent the 
// top-left most point of the rectangle by looking for the lowest value:
int stringX = Math.min(drawStart.x, drawEnd.x);
int stringY = Math.min(drawStart.y, drawEnd.y) + fontAscent;
// To add n pixles of padding between the rectangle edge and the string,
// just add n to the numbers passed in to the drawString() method here:
g.drawString(text, stringX  stringY);

请注意,上面的代码并未尝试确保文本适合矩形。为此,您需要使用 fm.stringWidth(text),然后决定是否要裁剪绘制的文本、缩放它或减小字体大小直到它适合(它可能永远不会这样做)。所有这些都超出了这个问题的范围。

编辑

最近更改代码后,您现在在绘制方法中绘制字符串时遇到问题。问题是您没有在任何地方保存 JOptionPane.showInputDialog 返回的字符串。它被分配给一个名为 text 的局部范围变量,然后被丢弃。 (请注意,这不是 class 级变量 text,因为您通过再次为其指定类型来声明一个新的局部变量;即,您正在使用 String text = ...。但这不是实际问题。事实上,您可以摆脱 class-level text 变量并在拖动矩形时停止绘制它;不需要它。)

正如您已经在 class 级变量中存储了一个形状列表,以便在每次调用 paint() 时重新绘制,您还需要存储一个要绘制的字符串列表以及绘制它们的点。所以你需要一个新的 class 来将字符串与点相关联:

class DrawnString {
    private final String text;
    private final Point position;
    // Insert constructor and getter methods here
}

然后您还需要 DrawingBoard 中的 class 级列表来存储这些实例,就像您的形状列表一样:

private List<DrawnString> strings = new ArrayList<DrawnString>();

现在,回到您的 mouseReleased 方法,在从 JOptionPane 获取文本之后,但在调用 repaint() 之前,您应该将字符串及其位置添加到 DrawnStrings 列表中。

// Note that you need to do this BEFORE you set drawStart and drawEnd to 
// null, so move the lines where that is done to below these lines:
int stringX = Math.min(drawStart.x, drawEnd.x);
int stringY = Math.min(drawStart.y, drawEnd.y);

// now it's safe to discard these points:
drawStart = null;
drawEnd = null;

// Now save the string and its position in the list so that it can be 
// redrawn every time paint() is called:
strings.add(new DrawnString(text, new Point(stringX, stringY)));

// Now we can call repaint():
repaint(); 

最后,在您的 paint() 方法中,绘制完所有形状后(即,在 for (Shape s : shapes) 循环之后),您应该绘制字符串:

// This is where you need to get the size of the font
FontMetrics fm = graphSettings.getFontMetrics();
int fontAscent = fm.getAscent();

for (DrawnString s : strings) {
    Point p = s.getPosition();
    // Draw with 2px padding, for example:
    graphSettings.drawString(s.getText(), p.x + 2, p.y + fontAscent + 2);
}

最后,在 paint() 方法的末尾,在 if (currentAction == 4) {...} 块内,去掉那里的绘制字符串内容(即 //Add text inside the rectangle 评论之后的所有内容)。

瞧瞧!