トップ 差分 一覧 ソース 置換 検索 ヘルプ PDF RSS ログイン

Swingのラベル等の文字列省略について

http://www.ne.jp/asahi/hishidama/home/tech/java/swing/JLabel.html

JLabel等の文字列の省略

JLabelやJComboBoxなどで表示されている文字列がコンポーネントのサイズを超えると、文字列の最後が「...」になって省略される。

これは、BasicLabelUI#layoutCL() から SwingUtilities.layoutCompoundLabel() を呼び出して、省略した文字列の取得や表示座標を計算している。

 省略文字列を変更する

JLabelやJComboboxの省略文字を変更するにはオリジナルのLabelUIを作成して省略文字の処理を変更する

サンプル

以下は、文字列の最後ではなく、途中を省略するサンプル。
真ん中の左右の文字列の幅は、プロポーショナルフォントを考慮して、バイナリサーチで計算する。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
class MetalLabelUIForMiddleClip extends MetalLabelUI {
  protected String layoutCL(
    JLabel label,                  
    FontMetrics fontMetrics, 
    String text, 
    Icon icon, 
    Rectangle viewR, 
    Rectangle iconR, 
    Rectangle textR)
  {
    String clipString = "...";
    int clipLength = clipString.length();
    int clipWidth = fontMetrics.stringWidth(clipString);
    
    int width = viewR.width - viewR.x;
    if (icon != null){
      width = width - (icon.getIconWidth() + label.getIconTextGap());
    }
    
    // 超える可能性あり
    if (fontMetrics.stringWidth(text) > width ){
      // System.out.println(viewR);
      // System.out.println(iconR);
      // System.out.println(icon.getIconWidth());
      // System.out.println(label.getIconTextGap());
      
      int middleWidth = (width - clipWidth ) / 2;
      
      int length = text.length();
      int middle = length / 2;
      
      String left = text.substring(0, middle);
      left = cutString(left, fontMetrics, middleWidth);
      
      String right = text.substring(middle, length);
      StringBuilder sb = new StringBuilder(right);
      ;
      right = sb.reverse().toString();
      right = cutString(right, fontMetrics, middleWidth);
      sb.delete(0, sb.length());
      right = sb.append(right).reverse().toString();
      
      sb.delete(0, sb.length());
      sb.append(left).append("...").append(right);
      // System.out.println(left);
      // System.out.println(right);
      text = sb.toString();
    }
    // System.out.println(text);
    
    return SwingUtilities.layoutCompoundLabel(
      (JComponent) label,
      fontMetrics,
      text,
      icon,
      label.getVerticalAlignment(),
      label.getHorizontalAlignment(),
      label.getVerticalTextPosition(),
      label.getHorizontalTextPosition(),
      viewR,
      iconR,
      textR,
      label.getIconTextGap());
  }
  
  protected String cutString(String text, FontMetrics fm, int width){
    if (width <= 0){
      return "";
    }
    
    if (fm.stringWidth(text) <= width){
      return text;
    }
    
    int left = 0;
    int right = text.length();
    int middle = 0;
    while(right - left > 1){
      middle = left + (right - left) / 2;
      if (fm.stringWidth(text.substring(0, middle)) > width){
        right = middle;
      } else {
        left = middle;
      }
    }
    
    // 最後の2つのどちらか
    if (fm.stringWidth(text.substring(0, right)) > width){
      right = left;
    }
    return text.substring(0, right);
  }
}

このLabelUIを使うには

JLabelの場合

JLabel test = new JLabel("aaaaaaaaaaaaaaaaaaaaaaaaaaaa");
test.setUI(new MetalLabelUIForMiddleClip ());

JComboBoxの場合

 JComboBox cb = new JComboBox(new Object[]{"aaaaaaaaaaaaaaaa"});
 ListCellRenderer renderer =  cb.getRenderer();
 if (!(renderer instanceof JLabel)){
   return;
 }
 LabelUI labelui = ((JLabel)renderer).getUI();
 if (!MetalLabelUI.class.equals(labelui.getClass())){
   return;
 }
 ((JLabel)renderer).setUI(new MetalLabelUIForMiddleClip());

[カテゴリ: プログラミング言語 > Java]

[通知用URL]



  • Hatenaブックマークに追加
  • livedoorクリップに追加
  • del.icio.usに追加
  • FC2ブックマークに追加

最終更新時間:2014年11月12日 22時41分40秒