Как отключить автоматическую поддержку HTML JLabel?

Swing JLabel автоматически интерпретирует любой текст как содержимое HTML, если он начинается с . Если содержимое этого HTML-изображения является изображением с недопустимым URL-адресом, это приведет к зависанию всего графического интерфейса, так как ImageFetche, который должен загрузить это изображение, выйдет из NPE.

Чтобы воспроизвести эту проблему, просто создайте JLabel следующим образом

new JLabel("<html><img src='http:\\\\invalid\\url'>")

Я знаю, что есть свойство client, которое не позволяет JLabel интерпретировать HTML. Но JLabel является реализацией рендерера по умолчанию для многих компонентов Swing (таких как JTree, JTable и т. Д.), Что делает это проблемой практически для любого приложения Swing, которое допускает ввод данных пользователем. Поэтому вместо реализации множества пользовательских средств визуализации я ищу глобальное решение для отключения интерпретации HTML.

8
задан tigger 27 August 2010 в 12:49
поделиться

3 ответа

Есть способ, если вы создадите свой собственный внешний вид.
Я не уверен, насколько хорошо это работает, но это работает. Предположим, вы расширите L&F «Классической Windows». Вам нужно как минимум 2 класса. Одним из них является сам Look&Feel, назовем его WindowsClassicLookAndFeelExt. Вам нужно только переопределить метод initClassDefaults.

package testSwing;

import javax.swing.UIDefaults;
import com.sun.java.swing.plaf.windows.WindowsClassicLookAndFeel;

public class WindowsClassicLookAndFeelExt extends WindowsClassicLookAndFeel    {
    @Override protected void initClassDefaults(UIDefaults table){
        super.initClassDefaults(table);
        Object[] uiDefaults = { "LabelUI", WindowsLabelExtUI.class.getCanonicalName()};
        table.putDefaults(uiDefaults);
    }
}

Вам также нужен класс WindowsLabelExtUI для управления всеми JLabels и установки свойства:

package testSwing;
import javax.swing.JComponent;
import javax.swing.plaf.ComponentUI;
import com.sun.java.swing.plaf.windows.WindowsLabelUI;

public class WindowsLabelExtUI extends WindowsLabelUI{
    static WindowsLabelExtUI singleton = new WindowsLabelExtUI();

    public static ComponentUI createUI(JComponent c){
        c.putClientProperty("html.disable", Boolean.TRUE);    
        return singleton;
    }
}

И, наконец, тестовый класс, когда вы устанавливаете тему как WindowsClassicLookAndFeelExt

package testSwing;

import java.awt.FlowLayout;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JScrollPane;
import javax.swing.UIManager;


public class Main{
    public static void main(String[] args){
        try{                UIManager.setLookAndFeel(WindowsClassicLookAndFeelExt.class.getCanonicalName());
        }catch (Exception e){
            e.printStackTrace();
        }

        JFrame frame = new JFrame("JList Test");
        frame.setLayout(new FlowLayout());
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        String[] selections = {"<html><img src='http:\\\\invalid\\url'>", "<html><H1>Hello</h1></html>", "orange", "dark blue"};

        JList list = new JList(selections);

        list.setSelectedIndex(1);
        System.out.println(list.getSelectedValue());

        JLabel jLabel = new JLabel("<html><h2>standard Label</h2></html>");
        frame.add(new JScrollPane(list));
        frame.add(jLabel);
        frame.pack();

        frame.setVisible(true);
    }
}

И вы увидите что-то вроде

alt text

4
ответ дан 5 December 2019 в 21:15
поделиться

Для простого JLabel вы можете вызвать метод JComponent

myLabel.putClientProperty("html.disable", Boolean.TRUE);

на метке, где вы хотите отключить рендеринг HTML.

Ссылка: Невозможно отключить рендеринг HTML в JLabel


Для чего-то вроде JTable, JTree или JList вам потребуется создать пользовательский модуль рендеринга ячеек, который задает это свойство. Вот пример (измененный из этого примера), в котором создается пользовательский модуль визуализации ячеек для JList.

import java.awt.Component;
import java.awt.FlowLayout;

import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JScrollPane;
import javax.swing.ListCellRenderer;

public class JListTest {
    public static void main(String[] args) {
        JFrame.setDefaultLookAndFeelDecorated(true);
        JFrame frame = new JFrame("JList Test");
        frame.setLayout(new FlowLayout());
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        String[] selections = { "<html><img src='http:\\\\invalid\\url'>",
                "red", "orange", "dark blue" };
        JList list = new JList(selections);

        // set the list cell renderer to the custom class defined below
        list.setCellRenderer(new MyCellRenderer());

        list.setSelectedIndex(1);
        System.out.println(list.getSelectedValue());
        frame.add(new JScrollPane(list));
        frame.pack();

        frame.setVisible(true);
    }
}


class MyCellRenderer extends JLabel implements ListCellRenderer {
    public MyCellRenderer() {
        setOpaque(true);
        putClientProperty("html.disable", Boolean.TRUE);
    }

    public Component getListCellRendererComponent(
        JList list,
        Object value,
        int index,
        boolean isSelected,
        boolean cellHasFocus)
    {
        setText(value.toString());
        return this;
    }
}

Я использовал пример кода из документации ListCellRenderer в качестве отправной точки для пользовательского средства визуализации ячеек списка.

Когда я запускаю пример, вы видите, что HTML-код в первой записи списка отображается, а не интерпретируется.

JList Custom Renderer

2
ответ дан 5 December 2019 в 21:15
поделиться

Повешение, вероятно, наименее неприятное поведение. Вот почему проверка данных так важна. Просто не позволяйте пользователям вводить что-то подобное.

1
ответ дан 5 December 2019 в 21:15
поделиться
Другие вопросы по тегам:

Похожие вопросы: