Я пытаюсь визуально центрировать произвольную строку, предоставленную пользователем, на JPanel. Я прочитал десятки других подобных вопросов и ответов здесь, на SO, но не нашел того, что непосредственно решает проблему, которую я имею.
В примере кода ниже getWidth() и getHeight() ссылаются на ширину и высоту JPanel, на которую я помещаю текстовую строку. Я обнаружил, что TextLayout.getBounds() очень хорошо говорит мне размер ограничивающего прямоугольника, который заключает в себе текст. Итак, я решил, что было бы относительно просто центрировать текстовый прямоугольник в прямоугольнике JPanel, вычисляя позиции x и y на JPanel нижнего левого угла прямоугольника, ограничивающего текст:
FontRenderContext context = g2d.getFontRenderContext();
messageTextFont = new Font("Arial", Font.BOLD, fontSize);
TextLayout txt = new TextLayout(messageText, messageTextFont, context);
Rectangle2D bounds = txt.getBounds();
xString = (int)((getWidth() - (int)bounds.getWidth()) / 2 );
yString = (int)((getHeight()/2) + (int)(bounds.getHeight()/2));
g2d.setFont(messageTextFont);
g2d.setColor(rxColor);
g2d.drawString(messageText, xString, yString);
Это отлично работало для строк, которые были прописными. Однако, когда я начал тестировать строки, содержащие строчные буквы с descenders (например, g, p, y), текст больше не был центрирован. Опускатели на строчных буквах (части, которые простираются ниже базовой линии шрифта) были слишком низки на JPanel, чтобы текст выглядел центрированным.
Что, когда я обнаружил (благодаря SO), что параметр y, переданный в drawString(), указывает базовую нарисованного текста, а не нижнюю границу. Таким образом, снова с помощью SO я понял, что мне нужно настроить размещение текста по длине descenders в моей строке:
....
TextLayout txt = new TextLayout(messageText, messageTextFont, context);
Rectangle2D bounds = txt.getBounds();
int descent = (int)txt.getDescent();
xString = (int)((getWidth() - (int)bounds.getWidth()) / 2 );
yString = (int)((getHeight()/2) + (int)(bounds.getHeight()/2) - descent);
....
Я тестировал это со строками, тяжелыми строчными буквами, такими как g, p и y, и он отлично работает! WooHoo! Но ждать. Тьфу. Теперь, когда я пытаюсь только заглавными буквами, текст слишком высокий для JPanel, чтобы выглядеть центрированным.
Что, когда я обнаружил, что TextLayout.getDescent() (и все остальные методы getDescent(), которые я нашел для других классов), возвращает максимальный спуск FONT а не конкретной строки. Таким образом, моя верхняя строка была поднята для учета descenders, которые даже не встречались в этой строке.
Что мне делать? Если я не настрою параметр y для drawString() для учетной записи для descenders, то строчные строки с descenders визуально слишком низки на JPanel. Если я отредактирую параметр y для drawString() для учета descenders, тогда строки, которые не содержат никаких символов с descenders, визуально слишком высоки на JPanel. Кажется, мне не удалось определить, где базовая линия находится в прямоугольнике, ограничивающем текст, для строки GIVEN. Таким образом, я не могу точно определить, что y передать drawString().
Спасибо за любую помощь или предложения.