15

<html> で始まるテキストは、Swing JLabel によって HTML コンテンツとして自動的に解釈されます。この HTML のコンテンツが無効な URL を持つ画像である場合、この画像をロードする ImageFetche が NPE によって終了するため、GUI 全体がハングします。

この問題を再現するには、次のように JLabel を作成するだけです

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

JLabel が HTML を解釈しないようにするクライアント プロパティがあることは知っています。しかし、JLabel は多くの Swing コンポーネント (JTree、JTable など) のデフォルトのレンダラー実装であるため、ユーザー入力を許可するほぼすべての Swing アプリケーションでこれが問題になります。そのため、大量のカスタム レンダラーを実装する代わりに、HTML 解釈を無効にするグローバル ソリューションを探しています。

4

4 に答える 4

9

独自のルック アンド フィールを作成する方法があります。
これがどれだけうまく機能するかはわかりませんが、機能します。「Classic Windows」L&F を拡張するとします。少なくとも 2 つのクラスが必要です。1 つは 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);
    }
}

すべての JLabels を管理し、プロパティを設定するには、WindowsLabelExtUI クラスも必要です。

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);
    }
}

そして、あなたは次のようなものを見るでしょう

代替テキスト

于 2010-08-27T19:24:25.940 に答える
5

単純な JLabel の場合、JComponent メソッドを呼び出すことができます

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

HTML レンダリングを無効にするラベルの

参照: JLabel で HTML レンダリングを無効にすることはできません


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 カスタム レンダラー

于 2010-08-27T12:58:53.943 に答える
3

ぶら下がることは、おそらく最も不快な行動です。これが、データ検証が非常に重要である理由です。ユーザーがそのようなものを入力することを許可しないでください。

于 2010-08-27T14:51:00.587 に答える