TITLE:JTextPane、JLabelなどで複数行を表示

Posted by terai at 2006-06-10

JLabel、JTextAreaなどで複数行を表示

JTextPane、JTextArea、JLabelを使った複数行のラベルをテストします。

  • &jnlp;
  • &jar;
  • &zip;

#screenshot

サンプルコード

private final JTextPane label1 = new JTextPane();
private final JTextArea label2 = new JTextArea();
private final JLabel    label3 = new JLabel();
public MainPanel() {
  super(new GridLayout(3,1));
  ImageIcon icon = new ImageIcon(getClass().getResource("wi0124-32.png"));

  SimpleAttributeSet attr = new SimpleAttributeSet(); 
  StyleConstants.setLineSpacing(attr, -0.2f); 
  label1.setParagraphAttributes(attr, true); 

  label1.setText("JTextPane\nasdfasdf");
  label2.setText("JTextArea\nasdfasdf");
  label3.setText("<html>JLabel+html<br>asdfasdf");
  label3.setIcon(icon);

  add(setLeftIcon(label1, icon));
  add(setLeftIcon(label2, icon));
  add(label3);
  setPreferredSize(new Dimension(200, 200));
}
private static Box setLeftIcon(JTextComponent label, ImageIcon icon) {
  label.setForeground(UIManager.getColor("Label.foreground"));
  //label.setBackground(UIManager.getColor("Label.background"));
  label.setOpaque(false);
  label.setEditable(false);
  label.setFocusable(false);
  label.setMaximumSize(label.getPreferredSize());
  label.setMinimumSize(label.getPreferredSize());

  JLabel l = new JLabel(icon);
  l.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
  Box box = Box.createHorizontalBox();
  box.add(l);
  box.add(Box.createHorizontalStrut(2));
  box.add(label);
  box.add(Box.createHorizontalGlue());
  return box;
}

解説

  • 上:JTextPane
    • 文字色、背景色を変更し、編集不可、フォーカスの取得不可にしたJTextPaneを使用
    • \nを使って改行し複数行を表示
    • SimpleAttributeSetを使って、行間を詰めている
  • 中:JTextArea
    • 文字色、背景色を変更し、編集不可、フォーカスの取得不可にしたJTextAreaを使用
    • \nを使って改行し複数行を表示
  • 下:JLabel+html
    • JLabelの文字列にhtmlタグを使用
    • <br>タグを使って改行し複数行を表示

参考リンク

コメント

  • JDK 6 で、htmlタグを使ったJLabelでの複数行表示がすこし変更されているみたいです(Windows環境)。行間が詰まって見易くなっているようで、わざわざJTextPane+SimpleAttributeSetで行間を調節する必要もなさそうです。 -- terai
  • label.setBackground(UIManager.getColor("Label.background"));*1をlabel.setOpaque(false);に変更しました。 -- terai
  • はじめまして。Java初心者なのですが、JLabelで英字フォントを指定するとギザギザで表示されるのですが、ギザギザをなくすにはどうしたらよいでしょうか?ネットで探すと「setRenderingHint」を使うとできると出てはくるのですが、JLabelを使った場合の例が出てこなくて。。。ご教授よろしくお願いします。 -- ばしばし
    • こんばんは。「Java SE 6完全攻略」第17回 文字に対するアンチエイリアス:ITproにいろんな環境での方法がまとめられています。自宅の環境(Windows XP + java1.6.0_03)では、以下のようにオプションを設定して起動するとアンチエイリアスが掛かるようです(XPの画面のプロパティ、デザイン、効果をClearTypeに変更してもなぜかうまくいかない…)。 -- terai
      java -Dawt.useSystemAAFontSettings=on -cp ".\target\classes" example.MainPanel
  • ありがとうございます。なるほど、いろいろ書かれていますね!明日試してみます! -- ばしばし
  • こんにちは。当方の環境がJDK1.5であったので、非標準の「-Dswing.aatext=true」を設定するとアンチエイリアスがかかりました。けれども、標準ではどうするのかと言う疑問が。。。 -- ばしばし
    • ども。Sunに「1.5にも標準のオプション用意して」とお願いする…のはひとまず置いといて…。「Java Swing Hacks」本では、テキストにアンチエイリアスを適用するためだけのLook & Feel(Wrap Look And Feel - L2FProd.com)を使用する方法が紹介(HACK#52)されています。これを使えば、「-Dswing.aatext=true」無しで、1.5でもアンチエイリアスが掛かります。 -- terai
    • もし、一部のJLabelをアンチエイリアスするだけでいいのなら、以下のようにJLabel#paintComponentメソッドをオーバーライドしてしまうのが手っ取り早いかもしれません。 -- terai
      JLabel label = new JLabel("asdfasdfasdf") {
        @Override
        protected void paintComponent(Graphics g) {
          Graphics2D g2d = (Graphics2D)g;
          g2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING,
                               RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
          g2d.setRenderingHint(RenderingHints.KEY_RENDERING,
                               RenderingHints.VALUE_RENDER_QUALITY);
          super.paintComponent(g2d);
        }
      };
      
  • お返事遅くなりましたm(__)m。試してみます!ありがとうございます! -- ばしばし
  • JLabelでhtmlを使用するとsetEnabled(false)でグレーアウトしてくれないです。どうしたものでしょう。 -- ApplePedlar
  • こんにちは。ココのおかげでとても助かっています。ところで、1行の高さ(文字の高さを含めた高さ)を指定したい、というときには、setLineSpacingではダメってことですよね?「指定したい高さ-フォントの大きさ」をsetLineSpacingで指定してあげなきゃいけないんですよね?(文字サイズによって1行の高さが揃わなくなるのはイヤで揃えたいなと思うのですが、フォントによってそれだと、そうすると、フォントの大きさを変えるたびに指定しなおさなきゃいけないってことですよね。面倒…) -- びびあず
    • こんにちは。どういたしまして。LineSpacingはフォントサイズに依存するみたいですね。固定の間隔を指定するのなら、例えば以下のように、ParagraphView#getBottomInsetメソッドなどをオーバーライドするのが簡単かも。 -- terai
      import java.awt.*;
      import java.awt.event.*;
      import javax.swing.*;
      import javax.swing.text.*;
      public class MainPanel extends JPanel{
        private final JTextPane editor = new JTextPane();
        public MainPanel() {
          super(new BorderLayout());
          editor.setEditorKit(new MyEditorKit());
      //     SimpleAttributeSet a = new SimpleAttributeSet(); 
      //     StyleConstants.setLineSpacing(a, 1.0f);
      //     editor.setParagraphAttributes(a, true);
          editor.setText("12341234\nasdf_fASdfasf_fasdf_affffFSDdfasdf\nasdfasFasdf");
          SimpleAttributeSet attr = new SimpleAttributeSet();
          StyleConstants.setFontSize(attr, 32);
          try{
            Document doc = editor.getDocument();
            doc.insertString(doc.getLength(), "12341234\nasdfasdf", attr);
            editor.setCaretPosition(doc.getLength());
          }catch(BadLocationException e) {}
          add(new JScrollPane(editor));
          setPreferredSize(new Dimension(320, 240));
        }
        public static void main(String[] args) {
          EventQueue.invokeLater(new Runnable() {
            public void run() {
              createAndShowGUI();
            }
          });
        }
        public static void createAndShowGUI() {
          JFrame frame = new JFrame();
          frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
          frame.getContentPane().add(new MainPanel());
          frame.pack();
          frame.setLocationRelativeTo(null);
          frame.setVisible(true);
        }
      }
      class MyEditorKit extends StyledEditorKit {
        @Override public ViewFactory getViewFactory() {
          return new MyViewFactory();
        }
      }
      class MyViewFactory implements ViewFactory {
        @Override public View create(Element elem) {
          String kind = elem.getName();
          if(kind!=null) {
            if(kind.equals(AbstractDocument.ContentElementName)) {
              return new LabelView(elem);
            }else if(kind.equals(AbstractDocument.ParagraphElementName)) {
              return new ParagraphView(elem) {
                @Override protected short getBottomInset() {
                  return 5;
                }
              };
            }else if(kind.equals(AbstractDocument.SectionElementName)) {
              return new BoxView(elem, View.Y_AXIS);
            }else if(kind.equals(StyleConstants.ComponentElementName)) {
              return new ComponentView(elem);
            }else if(kind.equals(StyleConstants.IconElementName)) {
              return new IconView(elem);
            }
          }
          return new LabelView(elem);
        }
      }
      
  • (変な日本語を書いてましたね、失礼しました。) ところで…、さっそくご親切にソースまで書いて教えていただけて嬉しいです。ありがとうございました。これを参考にして、また勉強したいと思います。本当にありがとうございました。 -- びびあず
  • Swing初心者です。JTextPaneでの複数行表示、大変参考になりました。複数行表示自体はおかげ様でうまくいったのですが、ボーダーが思い通りにならず困っています。TitledBorderを設定しているのですが、タイトルを囲む線の外側(コンポーネントの枠)がくぼんだ状態になってしまいます。外枠は表示させたくないのですが、どこかでOFFできるのでしょうか。ご教授いただければ幸いです。 -- ka-ka
    • こんばんは。TitleBorderの枠線を変更する場合は、label.setBorder(BorderFactory.createTitledBorder(BorderFactory.createEmptyBorder(), "title")); のように、他のBorder(この場合、EmptyBorderで非表示にしている)と組み合わせて使用します。TitledBorder (Java Platform SE 6) -- terai
  • ありがとうございます。NetBeansで開発しているのですが、あ~でもないこ~でもないとプロパティ画面をいじっていたら、JScrollPaneとJtextPaneの組み合わせで思い描いたものはできました。SwingもNetBeansも初めてなので色々と思い通りにできずに四苦八苦しております。。。今後ともこちらのサイトで勉強させていただきます! -- ka-ka