Как вывести строку в несколько строк с помощью графики

Моя программа переопределяет public void paint(Graphics g, int x, int y);, чтобы рисовать некоторые укусы с помощью g.drawString(someString, x+10, y+30);

Теперь someString может быть довольно длинным, и поэтому он может не помещаться в одной строке.

Как лучше всего написать текст в несколько строк.
Например, в прямоугольнике (x1, y1, x2, y2)?

Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
11
0
14 409
5
Перейти к ответу Данный вопрос помечен как решенный

Ответы 5

java.awt.font.TextLayout может быть полезным. Вот фрагмент их примера кода:

   Graphics2D g = ...;
   Point2D loc = ...;
   Font font = Font.getFont("Helvetica-bold-italic");
   FontRenderContext frc = g.getFontRenderContext();
   TextLayout layout = new TextLayout("This is a string", font, frc);
   layout.draw(g, (float)loc.getX(), (float)loc.getY());

   Rectangle2D bounds = layout.getBounds();
   bounds.setRect(bounds.getX()+loc.getX(),
                  bounds.getY()+loc.getY(),
                  bounds.getWidth(),
                  bounds.getHeight());
   g.draw(bounds);

В противном случае вы всегда можете использовать текстовый элемент Swing, чтобы выполнить эту работу за вас, просто передайте графику, в которую вы хотите, чтобы он рисовал.

Я уже получил это. Моя проблема в том, что мне нужен не прямоугольник вокруг текста, а текст внутри данного прямоугольника.

Burkhard 27.10.2008 13:59

Обратите внимание, что конструктор TextLayout недокументированно выдает исключение, если переданная вами строка пуста.

Ricky Clarkson 22.02.2013 04:51

Используйте Shape labelShape = textLayout1.getOutline (null); а затем g2d.fill (labelShape); они должны устранить границу

mk7 15.12.2015 22:50

Постепенно создавайте свою строку, по одному слову за раз, используя метод Эпаги, чтобы найти длину вашей строки. Как только длина будет больше, чем ваш прямоугольник, удалите последнее слово и напечатайте. Повторяйте, пока у вас не закончатся слова.

Звучит как плохой алгоритм, но для каждой строки это действительно O (screenWidth / averageCharacterWidth) => O (1).

Тем не менее, используйте StringBuffer для создания своей строки!

Это не будет иметь временной сложности O (1); O (n), возможно, поскольку вам нужно (по крайней мере) добавить слово (т.е. добавить количество символов в StringBuilder.append), пока все символы не будут израсходованы.

jamesh 27.10.2008 15:43

Кажется, я плохо выражаюсь ... Я имел в виду, что каждая строка - O (1). Вы можете набросить на него 1000 слов, но для каждой строки он перестанет добавлять слова на краю экрана. В целом, да, O (n).

Ryan Fox 27.10.2008 21:17

Это работает только в том случае, если вы предполагаете, что строка будет не более 2 строк, когда ее будет больше, это не сработает.

Cyril N. 13.01.2012 00:31
Ответ принят как подходящий

Благодаря подсказке Эпаги и паре примеров в сети (не столь очевидных, чтобы найти! Я использовал в основном Разорвать строку для макета текста), я смог создать компонент для отображения текста в оболочке. Он неполный, но, по крайней мере, показывает желаемый эффект.

class TextContainer extends JPanel
{
    private int m_width;
    private int m_height;
    private String m_text;
    private AttributedCharacterIterator m_iterator;
    private int m_start;
    private int m_end;

    public TextContainer(String text, int width, int height)
    {
        m_text = text;
        m_width = width;
        m_height = height;

        AttributedString styledText = new AttributedString(text);
        m_iterator = styledText.getIterator();
        m_start = m_iterator.getBeginIndex();
        m_end = m_iterator.getEndIndex();
    }

    public String getText()
    {
        return m_text;
    }

    public Dimension getPreferredSize()
    {
        return new Dimension(m_width, m_height);
    }

    public void paint(Graphics g)
    {
        super.paintComponent(g);

        Graphics2D g2 = (Graphics2D) g;
        FontRenderContext frc = g2.getFontRenderContext();

        LineBreakMeasurer measurer = new LineBreakMeasurer(m_iterator, frc);
        measurer.setPosition(m_start);

        float x = 0, y = 0;
        while (measurer.getPosition() < m_end)
        {
            TextLayout layout = measurer.nextLayout(m_width);

            y += layout.getAscent();
            float dx = layout.isLeftToRight() ?
                    0 : m_width - layout.getAdvance();

            layout.draw(g2, x + dx, y);
            y += layout.getDescent() + layout.getLeading();
        }
    }
}

Ради интереса я сделал его обтекаемым по кругу (увы, похоже, нет оправдания):

public void paint(Graphics g)
{
    super.paintComponent(g);

    Graphics2D g2 = (Graphics2D) g;
    FontRenderContext frc = g2.getFontRenderContext();

    LineBreakMeasurer measurer = new LineBreakMeasurer(m_iterator, frc);
    measurer.setPosition(m_start);

    float y = 0;
    while (measurer.getPosition() < m_end)
    {
        double ix = Math.sqrt((m_width / 2 - y) * y);
        float x = m_width / 2.0F - (float) ix;
        int width = (int) ix * 2;

        TextLayout layout = measurer.nextLayout(width);

        y += layout.getAscent();
        float dx = layout.isLeftToRight() ?
                0 : width - layout.getAdvance();

        layout.draw(g2, x + dx, y);
        y += layout.getDescent() + layout.getLeading();
    }
}

Однако я не слишком уверен в вычислении dx.

Вы можете использовать JLabel и вставлять текст с помощью html.

JLabel.setText("<html>"+line1+"<br>"+line2);

Ваш HTML удаляется. Я предполагаю, что первый строковый литерал - это <html>, а второй - <br>.

Michael Myers 27.10.2008 16:40

Разве это не противоречит цели, если вам нужно добавлять собственные разрывы строк?

Ryan Fox 27.10.2008 21:21

У меня были проблемы, вот мое решение:

Graphics2D g=....
FontRenderContext frc = g.getFontRenderContext();
TextLayout layout = new TextLayout(text, font, frc);
String[] outputs = text.split("\n");
for(int i=0; i<outputs.length; i++){
    g.drawString(outputs[i], 15,(int) (15+i*layout.getBounds().getHeight()+0.5));

Надеюсь, что это поможет .... просто, но это работает.

Другие вопросы по теме