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.
Есть способ, если вы создадите свой собственный внешний вид.
Я не уверен, насколько хорошо это работает, но это работает. Предположим, вы расширите 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);
}
}
И вы увидите что-то вроде
Для простого 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-код в первой записи списка отображается, а не интерпретируется.
Повешение, вероятно, наименее неприятное поведение. Вот почему проверка данных так важна. Просто не позволяйте пользователям вводить что-то подобное.