Centering String in Panel

2020-02-07 06:29发布

问题:

I'm trying to center a String in a Panel.

Currently I'm doing this:

public void paintComponent(Graphics g) {
        super.paintComponent(g);
            int stringWidth = 0;
            int stringAccent = 0;
            int xCoordinate = 0;
            int yCoordinate = 0;
            // get the FontMetrics for the current font
            FontMetrics fm = g.getFontMetrics();


        /** display new message */
        if (currentMessage.equals(message1)) {
            removeAll();
            /** Centering the text */
            // find the center location to display
            stringWidth = fm.stringWidth(message2);
            stringAccent = fm.getAscent();
            // get the position of the leftmost character in the baseline
            xCoordinate = getWidth() / 2 - stringWidth / 2;
            yCoordinate = getHeight() / 2 + stringAccent / 2;

            // draw String
            g.drawString(message2, xCoordinate, yCoordinate);
            currentMessage = message2;  // alternate message
        }
}

Is there a single method I can use to simplify this task?

For example:

public void paintComponent(Graphics g) {
            super.paintComponent(g);
            if (currentMessage.equals(message1)) {
                removeAll();
                // draw String centered (with one line of code)
            }
}

Just seems like I'm doing a lot of work just to center text.

回答1:

In the java standard library? No, you can always do something along this

private void drawStringMiddleOfPanel(String string, Graphics g) {
            String message2 = string;
            int stringWidth = 0;
            int stringAccent = 0;
            int xCoordinate = 0;
            int yCoordinate = 0;
            // get the FontMetrics for the current font
            FontMetrics fm = g.getFontMetrics();


        /** display new message */
            /** Centering the text */
            // find the center location to display
            stringWidth = fm.stringWidth(message2);
            stringAccent = fm.getAscent();
            // get the position of the leftmost character in the baseline
            xCoordinate = getWidth() / 2 - stringWidth / 2;
            yCoordinate = getHeight() / 2 + stringAccent / 2;

            // draw String
            g.drawString(message2, xCoordinate, yCoordinate);
            currentMessage = message2;  // alternate message
        }

With

public void paintComponent(Graphics g) {
        super.paintComponent(g);
        if (currentMessage.equals(message1)) {
            removeAll();
            drawStringMiddleOfPanel(message1, g);
        }
 }


回答2:

Try something like ...

xCoordinate = (getWidth() - stringWidth) / 2;
yCoordinate = ((getHeight() - fm.getHeight) / 2) + stringAccent;

Instead.

Take a look at Java center text in rectangle for additional details

Also, you could achieve the same thing using a JLabel on a JPanel with a GridBagLayout

Updated

Just noticed removeAll(); in paintComponent. This is not a good idea, as it can cause a new repaint request to posted to the event queue, putting your code into an infinte loop which could consume your CPU...

Updated with example

Side by side comparison of drawString and JLabel...(drawString on left, JLabel on right)

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridBagLayout;
import java.awt.GridLayout;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class CenterText {

    public static void main(String[] args) {
        new CenterText();
    }

    public CenterText() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                }

                JFrame frame = new JFrame("Testing");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.setLayout(new GridLayout(1, 2));
                frame.add(new CenterStringPane());
                frame.add(new CenterLabelPane());
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public class CenterStringPane extends ReferencePane {

        public CenterStringPane() {
            setFont(UIManager.getFont("Label.font"));
        }

        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            Graphics2D g2d = (Graphics2D) g.create();

            String text = "In the center";
            FontMetrics fm = g2d.getFontMetrics();
            int x = (getWidth() - fm.stringWidth(text)) / 2;
            int y = ((getHeight() - fm.getHeight()) / 2) + fm.getAscent();

            g2d.drawString(text, x, y);

            g2d.dispose();
        }
    }

    public class CenterLabelPane extends ReferencePane {

        public CenterLabelPane() {

            setLayout(new GridBagLayout());
            add(new JLabel("In the center"));

        }
    }

    public class ReferencePane extends JPanel {

        public ReferencePane() {
        }

        @Override
        public Dimension getPreferredSize() {
            return new Dimension(200, 200);
        }

        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            Graphics2D g2d = (Graphics2D) g.create();
            int halfX = getWidth() / 2;
            int halfY = getHeight() / 2;
            g2d.drawLine(halfX, 0, halfX, getHeight());
            g2d.drawLine(0, halfY, getWidth(), halfY);
            g2d.dispose();
        }
    }
}


回答3:

   public void paintComponent(Graphics g) {
        super.paintComponent(g);
        if (currentMessage.equals(message1)) {
            removeAll();
            int x=  (panel.getWidth() / 2) - str.length()/2;
            int y = (panel.getHeight() / 2);
            graphics.drawString(str, x, y);

        }
   }