9

誰かが HTML を提案する前に、なぜそれがオプションではないのかを後で説明します。テキスト セルを含む列を含むテーブルがあります。各セルのテキストの一部を強調表示できるようにする必要があります。たとえば、セルに「cat foo dog」が含まれている場合... foo を強調表示したい場合があります。

私の現在の方法は、レンダリングされる JLabel コンポーネントに html を配置するカスタム TableCellRenderer を使用することです。次に、セル内のテキストが長すぎて列幅に収まらない場合、この場合通常発生する通常の「...」なしでテキストが切り捨てられることに気付きました。したがって、ユーザーは、表示されていないテキストが他にもあることを知りませんでした。もう 1 つの問題は、元のテキスト自体に HTML が含まれている場合 (私の場合は HTML が含まれている場合がある)、セルが正しくレンダリングされないことでした。html をエスケープするだけでよいことはわかっていますが、前の問題がまだ残っています。

jlabel 以外のコンポーネントを使用すると、テーブルのセルが奇妙に見えます。誰か提案はありますか?ありがとう

4

3 に答える 3

9

さて、ここに解決策があります。

JLabelつまり、ハイライトを手動で描画するようにサブクラス化できます。メソッドをオーバーライドpaintComponentして実際の描画を行いFontMetrics、強調表示された領域を描画する場所を計算するために使用します。

耐え難いほど詳細な答えは次のとおりです。

基本的に、JLabelものを強調表示できるサブクラスを作成できます。私はこのようにします。多少異なる方法で行うこともできます:

強調表示する部分をラベルに伝えるメソッドを追加します。これは、強調表示された領域が 1 つだけ必要であると仮定すると、次のようになります。

public void highlightRegion(int start, int end) {
     // Set some field to tell you where the highlight starts and ends...
}

複数の領域が必要な場合は、単純なフィールドの代わりに ArrayList を使用してください。強調表示を解除する方法もおそらく役立つでしょう。

paintComponentここで、 のメソッドをオーバーライドする必要がありますJLabel。ここでは、いくつかの個別の手順を実行する必要があり、さまざまな方法または何かで整理する必要がある場合があります。簡単にするために、すべてを paint メソッドに入れます。

@Override
protected void paintComponent(Graphics g) {
  ...

最初に、ハイライトの物理的な寸法を把握する必要があります。これは、niceFontMetricsクラスを使用して行うことができます。FontMetrics使用している のクラスを作成しますFont

  FontMetrics metrics = new FontMetrics(getFont());

これで、ハイライトとなる長方形を作成するために必要なすべての情報を取得できます。開始位置、高さ、幅が必要です。これを取得するには、JLabel次のように のテキストの2 つの部分文字列が必要です。

  String start = getText().substring(0, startOfHighlight);
  String text = getText().substring(startOfHighlight, endOfHighlight);
  //You may also need to account for some offsets here:
  int startX = metrics.stringWidth(start);
  int startY = 0; //You probably have some vertical offset to add here.
  int length = metrics.stringWidth(text);
  int height = metrics.getHeight();

これで、残りのラベルを描画する前に、強調表示された領域を描画できます。

  g.fillRect(startX, startY, length, height);
  super.paintComponent(g);
}

もちろん、ハイライトを複数の行にまたがらせたい場合は、さらに作業が必要になります。

不思議に思っているなら、私は実際に以前にこのようなことを書きました。気まぐれで、 から独自のテキスト領域タイプのコンポーネントを作成することにしましたJPanel。これは基本的に、強調表示を処理する方法でした。車輪の再発明は、実際のプロジェクトではばかげているかもしれませんが、役に立つかもしれないランダムなことを教えてくれます...

于 2010-08-21T08:55:25.487 に答える
2

SwingX レンダラーの装飾メカニズムをリングに投げ込まずにはいられません。要件を解決する方法は、それを実行する Highlighter を実装することです。これは実際にはすでに行われていますが (まだ公式にサポートされていません)、X/MatchingTextHighlighterという名前の SwingLabs-Demos プロジェクトに隠され(両方が必要です)、アイコン、RToL-ComponentOrientation、alignment、ellipses に対処するために最近修正されました。 .

于 2011-10-27T08:02:06.767 に答える
2

それは素晴らしい答えであり、おそらく最良の解決策です。しかし、いくつかのより簡単な方法は、レンダリングに JLabel の代わりに JTextfield を使用することです。その後、JTextfields の強調表示機能を使用できます。

void highlightWhitespaceText(JTextField text)
    {
        text.setHighlighter(AbstractTableCellRenderer.defaultHighlighter);
        try
        {
            Matcher m = AbstractTableCellRenderer.whitespaceStartPattern.matcher(text.getText());
            if (m.matches())
            {
                text.getHighlighter().addHighlight(m.start(1), m.end(1), AbstractTableCellRenderer.highlightPainter);
            }
            m = AbstractTableCellRenderer.whitespaceEndPattern.matcher(text.getText());
            if (m.matches())
            {
                text.getHighlighter().addHighlight(m.start(1), m.end(1), AbstractTableCellRenderer.highlightPainter);
            }
        }
        catch (BadLocationException ble)
        {
            //
        }
    }

JTextfield のプロパティを変更して、他の点で jLabel のように見えるようにすることができます。

于 2010-10-27T13:58:02.860 に答える