Свинг HTML DrawString

Я пытаюсь создать какой-то специальный компонент для определенной цели, на этом компоненте мне нужно нарисовать строку HTML, вот пример кода:

 public class MyComponent extends JComponent{
     public MyComponent(){
        super();
     }

     protected void paintComponent(Graphics g){
        //some drawing operations...
        g.drawString("<html><u>text to render</u></html>",10,10);
     }
 }

К сожалению, метод drawString, похоже, не распознает формат HTML, он по глупости рисует строку такой, какая она есть.

Есть ли способ заставить это работать?


person George Casttrey    schedule 15.10.2011    source источник
comment
Почему вы не используете JLabel? Он поддерживает теги HTML.   -  person Eng.Fouad    schedule 15.10.2011
comment
Мой компонент не просто рисует html-строку, есть много других операций рисования, которые я не хотел показывать в примере кода, просто чтобы сосредоточиться на реальной проблеме.   -  person George Casttrey    schedule 15.10.2011
comment
"Особый" как? "Конкретно" что? Ответы на этот вопрос подразумевают, что лучше включить больше деталей, а не меньше.   -  person Andrew Thompson    schedule 15.10.2011


Ответы (7)


Если поклонник Java2D; но чтобы максимально эффективно использовать HTML в компонентах и ​​макетах Swing, я рекомендую вам использовать компонентный подход, предложенный @camickr. При необходимости вы можете использовать легковесный подход с визуализатором. видно в JTable, et al, в котором один компонент многократно используется для рисования. Пример ниже представляет собой очень упрощенную схему техники, в которой меняются только цвет и местоположение.

Приложение: обновленный пример; см. также CellRendererPane и Заставьте ваши приложения летать: внедрите Flyweight для улучшения производительность.

введите здесь описание изображения

import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import javax.swing.CellRendererPane;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;

/** @see http://stackoverflow.com/questions/7774960 */
public class PaintComponentTest extends JPanel {

    private static final int N = 8;
    private static final String s = "<html><big><u>Hello</u></html>";
    private JLabel renderer = new JLabel(s);
    private CellRendererPane crp = new CellRendererPane();
    private Dimension dim;

    public PaintComponentTest() {
        this.setBackground(Color.black);
        dim = renderer.getPreferredSize();
        this.add(crp);
    }

    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);
        for (int i = 0; i < N; i++) {
            renderer.setForeground(Color.getHSBColor((float) i / N, 1, 1));
            crp.paintComponent(g, renderer, this,
                i * dim.width, i * dim.height, dim.width, dim.height);
        }
    }

    private void display() {
        JFrame f = new JFrame("PaintComponentTest");
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        f.add(this);
        f.pack();
        f.setSize(dim.width * N, dim.height * (N + 1));
        f.setLocationRelativeTo(null);
        f.setVisible(true);
    }

    public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {

            @Override
            public void run() {
                new PaintComponentTest().display();
            }
        });
    }
}
person trashgod    schedule 15.10.2011
comment
огромное спасибо за помощь. Я нашел другой способ сделать это без использования CellRendererPane. (Посмотрите на мой пост с ответом). - person George Casttrey; 15.10.2011
comment
Пожалуйста. CellRendererPane предлагает несколько удобных оптимизаций буферизации. и проверка, которая еще может оказаться полезной в будущем. - person trashgod; 15.10.2011

Как уже отмечалось, компоненты Swing поддерживают HTML 3.2 и основные стили.

Подробнее о том, как использовать эту возможность в методе paintComponent(Graphics), см. в источнике LabelRenderTest.java на странице эта тема.

Подход заключается в том, чтобы отобразить метку в изображение, а затем отобразить изображение в объект Graphics.

person Andrew Thompson    schedule 15.10.2011
comment
Я нашел способ рисовать htmlString с помощью JLabel, но без необходимости рендеринга изображения (посмотрите мой пост). Огромное спасибо за помощь. - person George Casttrey; 15.10.2011

Ответ на ваш вопрос заключается в том, что HTML не поддерживается.

Простое решение — использовать компоненты Swing и правильно их размещать.

Если вы хотите сделать это самостоятельно, вам нужно манипулировать шрифтом, который вы используете для метода drawString(). Вы можете использовать шрифт с курсивом, полужирным шрифтом и т. д.

person camickr    schedule 15.10.2011
comment
Большое спасибо за ответ, он помог мне правильно мыслить. - person George Casttrey; 15.10.2011

Я нашел короткий и простой способ смоделировать paintHtmlString; вот код:

public class MyComponent extends JComponent {

    private JLabel label = null;

    public MyComponent() {
        super();
    }

    private JLabel getLabel() {
        if (label == null) {
            label = new JLabel();
        }
        return label;
    }

    /**
     * x and y stand for the upper left corner of the label
     * and not for the baseline coordinates ...
     */
    private void paintHtmlString(Graphics g, String html, int x, int y) {
        g.translate(x, y);
        getLabel().setText(html);
        //the fontMetrics stringWidth and height can be replaced by
        //getLabel().getPreferredSize() if needed
        getLabel().paint(g);
        g.translate(-x, -y);
    }

    protected void paintComponent(Graphics g) {
        //some drawing operations...
        paintHtmlString(g, "<html><u>some text</u></html>", 10, 10);
    }
}

Спасибо всем за помощь, я очень ценю это.

person George Casttrey    schedule 15.10.2011
comment
Как отмечено здесь, может потребоваться getLabel().setSize(getLabel().getPreferredSize()), если JLabel никогда не добавлялся в кадр, который был pack()ed (или эквивалент). - person Evgeni Sergeev; 09.10.2018

Это не способ реализации.

drawString(String str, int x, int y) рисует только текст, заданный указанной строкой, используя текущий шрифт и цвет этого графического контекста.

Вы можете получить дополнительную информацию о своей проблеме здесь, Как использовать HTML в Swing Компоненты

person COD3BOY    schedule 15.10.2011
comment
спасибо за ответ, это помогло мне пойти по правильному пути. - person George Casttrey; 15.10.2011

Используйте JLabel в качестве базового класса. Graphics.drawString() может только... нарисовать строку.

person Michał Šrajer    schedule 15.10.2011
comment
Мой компонент не просто рисует html-строку, есть много других операций рисования, которые я не хотел показывать в примере кода, просто чтобы сосредоточиться на реальной проблеме. Я знаю, что JLabel и все другие компоненты Swing, которые содержат текст, поддерживают формат html. ‹br/› Мне просто интересно, есть ли способ отображать html-тексты через экземпляр Graphics. - person George Casttrey; 15.10.2011
comment
Спасибо за полезный ответ. - person George Casttrey; 15.10.2011

Не существует простого способа рендеринга HTML для рисования с помощью Graphics, используйте JLabel.

Однако есть интересный способ сделать это, создав JLabel с помощью HTML и нарисовав его графику на компоненте:

private JLabel label;

public MyComponent() {
    label = new JLabel("Before Red");
    label.setText("<html><u>test</u></html>");
    this.add(label);
}

public void repaint(Graphics g){
    g = label.getGraphics();
}

Самый простой способ добиться этого — установить шрифт для вашей графики, например:

public void repaint(Graphics g){    
    Font f = new Font("Courier", Font.BOLD, 12);
    g.setFont(f);
    g.drawString("Bolded Courier", 5, 15);
}
person jpalm    schedule 15.10.2011