- PR -

長い文字列を表示する時には

1
投稿者投稿内容
会議室デビュー日: 2004/03/25
投稿数: 2
投稿日時: 2004-04-20 18:59
長い文字列を表示したい場合、皆様はどんなAWTコンポーネントを使用されますか?

例えばフレームの幅が100で、その上に文字列の長さが200とします。
文字列の長さは
private FontMetrics strFontM;
strFontM = Frame1.getFontMetrics(Font("Helvetica", Font.BOLD, 10));
StringLen = strFontM .stringWidth(longString);
ってな感じで取得した長さです。

文字列の長さがフレームの幅よりも長いので、表示する際に途中で折り返して2行で表示しなくてはなりません。

文字列を表示する物として
・ラベル(java.awt.label)
・テキストエリア(java.awt.TextArea)
・直接書くってのもありですね
が代表的だと思うのです。

ラベルは2行にして表示はできないですよね?どうしてもラベルに表示したい場合はラベルを
2枚用意する必要がありますよね?
だからテキストエリアか直接フレームに書くって方法しかないでしょうか?

質問がまとまりませんが、こんな方法もあるぞってのがありましたら教えてください。

*仕様上Swingは使えません。
かずくん
ぬし
会議室デビュー日: 2003/01/08
投稿数: 759
お住まい・勤務地: 太陽系第三惑星
投稿日時: 2004-04-20 22:42
ComponentやCanvasから派生した複数行表示できるラベルを作るというのは?

単純に折り返すだけなら、ラベル幅と文字幅から折り返し段数を計算し、ラベル幅X(文字高さX折り返し段数)のオフスクリーンイメージを作成する。
一行に表示できる文字数を計算しながら、オフスクリーンイメージに文字を描画した後、スクリーンのGraphicsにdrawImageでオフスクリーンイメージを転送するだけです。

単語単位での折り返しとなるとちょっと思いつきません。
シュン
ぬし
会議室デビュー日: 2004/01/06
投稿数: 328
お住まい・勤務地: 東京都
投稿日時: 2004-04-22 02:31
引用:

かずくんさんの書き込み (2004-04-20 22:42) より:
ComponentやCanvasから派生した複数行表示できるラベルを作るというのは?

単純に折り返すだけなら、ラベル幅と文字幅から折り返し段数を計算し、ラベル幅X(文字高さX折り返し段数)のオフスクリーンイメージを作成する。
一行に表示できる文字数を計算しながら、オフスクリーンイメージに文字を描画した後、スクリーンのGraphicsにdrawImageでオフスクリーンイメージを転送するだけです。



以下細かいことですが。

ラベル文字列にダブルバッファリングは必要なのでしょうか?
直接ペインのGraphicsにdrawString()しても良いかとおもいますが…

引用:

単語単位での折り返しとなるとちょっと思いつきません。



こういう用途には、java.text.BreakIteratorが利用できませんか?
会議室デビュー日: 2004/03/25
投稿数: 2
投稿日時: 2004-04-22 08:44
かずくん、シュンさんご意見ありがとうございます。

以下のようにしてみました。(見づらいですが・・・)
コード:
 int strLen = 0; //文字列の長さ
 int sizeFrameWidth = 100; //表示するフレームの幅
 int strDispLen = 0; //表示する文字列の長さ
 String str = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefghijklmnopqrstu..."
 String dispStr = ""; //表示する文字列
 ArrayList aryList = new ArrayList(); //表示する文字列格納
 int intStart = 0;
 int intEnd   = 0; 

 strLen = strFontM.stringWidth(str);
 if(strLen > sizeFrameWidth) { 
   //文字列の長さがフレーム幅より大きい場合
   while (true) {
     dispStr = String.valueOf(strMsg.substring(intStart, intEnd));
     strDispLen = strFontM.stringWidth(dispStr);
     if(strDispLen > sizeFrameWidth) {
       aryList.add(dispStr);
       if(intEnd >= str.length()) { break; }
       intStart = intEnd;
     }
     intCntEnd++;
     if(intEnd > str.length()) { aryList.add(dispStr); break; }
   }
 } else {
   //文字列の長さがメインフレームより小さい場合
   aryList.add(str);
 }



ただ単語単位での折り返しってのが良くわかりません。
シュンさんから教えていただいた"java.text.BreakIterator"をどのように使えばよいのか?
かずくん
ぬし
会議室デビュー日: 2003/01/08
投稿数: 759
お住まい・勤務地: 太陽系第三惑星
投稿日時: 2004-04-22 09:09
引用:

こういう用途には、java.text.BreakIteratorが利用できませんか?


これは、知りませんでした。これって、日本語と英単語が混じったものでも、切り分けれるんですかね?

引用:

ただ単語単位での折り返しってのが良くわかりません。
シュンさんから教えていただいた"java.text.BreakIterator"をどのように使えばよいのか?


使用法は、APIリファレンスを見てもらえばよろしいかと。
http://java.sun.com/j2se/1.4.2/docs/api/java/text/BreakIterator.html
ついでに、日本語と英単語入り混じり文が切り分けれるかの報告があると、うれしいなぁ。
さくらば
大ベテラン
会議室デビュー日: 2002/11/12
投稿数: 145
投稿日時: 2004-04-22 16:03
こんにちは、さくらばです。

引用:

かずくんさんの書き込み (2004-04-22 09:09) より:
引用:

こういう用途には、java.text.BreakIteratorが利用できませんか?


これは、知りませんでした。これって、日本語と英単語が混じったものでも、切り分けれるんですかね?



分けられます。日本語の単語は認識できませんが、禁則処理は行えます。

引用:

使用法は、APIリファレンスを見てもらえばよろしいかと。
http://java.sun.com/j2se/1.4.2/docs/api/java/text/BreakIterator.html
ついでに、日本語と英単語入り混じり文が切り分けれるかの報告があると、うれしいなぁ。



それよりも Java2D のTutorial の方がいいと思います。

http://java.sun.com/docs/books/tutorial/2d/textandfonts/linebreakmeasure.html

前の引用になってしまいますが、ご容赦ください。

引用:

ComponentやCanvasから派生した複数行表示できるラベルを作るというのは?



ラベルを作るのはいいと思いますが、Canvas のような Heavy-Weight な
コンポーネントを使う必要はないと思います。

# Canvas はコンパチを保つために残しているのだと個人的には思っています。

下の例はシンプルにするためにわざとダブルバッファリングをしていません。
ある程度文字列が長くなった場合は描画に時間がかかるようになるので、ダブル
バッファリング (特に BufferStrategy を使用したダブルバッファリング) は
不可欠だと思います。

コード:
import java.awt.Component;
import java.awt.Dimension;
import java.awt.Frame;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.awt.font.FontRenderContext;
import java.awt.font.LineBreakMeasurer;
import java.awt.font.TextAttribute;
import java.awt.font.TextLayout;
import java.text.AttributedCharacterIterator;
import java.text.AttributedString;
import java.util.Hashtable;
import java.util.StringTokenizer;

public class LineBreakSample extends Component {

    private Hashtable map = new Hashtable();
    private String text = 
        "東海の小島の磯の白砂にわれ泣きぬれて蟹とたはむる\n" +
        "日本語の、禁則について、試すため、点と、丸を、多く、書いてみます。これで、どうだろう。\n" +
        "  Once upon a midnight dreary, while I pondered, weak and weary, " +
        "Over many a quaint and curious volume of forgotten lore, " +
        "While I nodded, nearly napping, suddenly there came a tapping, " +
        "As of some one gently rapping, rapping at my chamber door. " +
        "\"Tis some visiter,\" I muttered, \"tapping at my chamber door -- " +
        "Only this, and nothing more.\n" + 
        "アルファベットとhiragana wo混ぜてkaitemimasita.どうなることやら";

    public LineBreakSample() {
        map.put(TextAttribute.SIZE, new Float(18.0));
    }

    public void paint(Graphics g) {
        Graphics2D g2d = (Graphics2D)g;

        float formatWidth = (float)getSize().width;
        float drawPosY = 0;
        
        StringTokenizer tok = new StringTokenizer(text, "\n");
        while (tok.hasMoreTokens()) {
            AttributedString attrStr = new AttributedString(tok.nextToken(), map);
            AttributedCharacterIterator line = attrStr.getIterator();

            int start = line.getBeginIndex();
            int end = line.getEndIndex();
            
            LineBreakMeasurer lineMeasurer = new LineBreakMeasurer(line,
                                           new FontRenderContext(null, false, false));
            lineMeasurer.setPosition(start);
            
            while (lineMeasurer.getPosition() < end) {
                
                TextLayout layout = lineMeasurer.nextLayout(formatWidth);
                drawPosY += layout.getAscent();
                
                float drawPosX;
                if (layout.isLeftToRight()) {
                    drawPosX = 0;
                } else {
                    drawPosX = formatWidth - layout.getAdvance();
                }
                
                layout.draw(g2d, drawPosX, drawPosY);
                
                drawPosY += layout.getDescent() + layout.getLeading();
            }
        }
    }

    public static void main(String[] args) {
        Frame frame = new Frame("HitTestSample");
        frame.addWindowListener(new WindowAdapter() {
            public void windowClosing(WindowEvent event) {
                System.exit(0);
            }
        });
        
        LineBreakSample sample = new LineBreakSample();
        frame.add(sample);
        frame.setBounds(100, 100, 400, 500);
        frame.setVisible(true);
    }
}


1

スキルアップ/キャリアアップ(JOB@IT)