12

Graphics2DJava のクラスを使用して多くの文字列を描画する必要があるアプリケーションを作成しようとしています。各 String オブジェクトのサイズを取得する必要があります (各文字列の正確な位置を計算するため)。paint()メソッドが呼び出される前に実行する必要がある文字列が非常に多く、プログラムの最初に一度だけ実行する必要があります(そのため、Graphics2Dまだオブジェクトがありません)。メソッドがあることは知っていますが、パラメーターとしてオブジェクトFont.getStringBounds()が必要です。FontRenderContext

独自のオブジェクトを作成しようとしたとき:

FontRenderContext frc = new FontRenderContext(MyFont.getTransform(), true, true)

次に、内部のメソッドFontRenderContextを使用して取得する場合とは常に異なるサイズを取得する文字列の境界を取得します。大きな違いはありませんが (約 1E-3)、なぜ違いがあるのでしょうか?Graphics2D.getFontRenderContext()paint()

ただし、文字列のサイズを取得するためのより適切で安全な方法はありますか?

事前に助けてくれてありがとう!

4

6 に答える 6

5

FontMetricsクラスを試してください。stringWidthメソッドは文字列のサイズを返します。例:

JComponent c = getSomeKindOfJComponent();
FontMetrics fm = c.getFontMetrics(c.getFont()); // or another font
int strw = fm.stringWidth("My text");
于 2011-02-06T15:38:27.977 に答える
3

ネヴァ。ごんな。起こる。

その理由は、FRC から探しているレンダリングと計算が Graphics コンテキスト、つまり特定の Graphics2D オブジェクトに固有であるためです。あなたが興味を持っているのは、実行時に渡されるものです-それは他に類を見ません(想定する必要があります)。

他のGraphics2Dから FRC を使用して必要なだけ計算できますが、実行時に Graphics2D paintComponent を使用して使用しようとすると、計算はすべて無駄になります。これは、使用する Graphics2D です。どのような。

はい、これは素晴らしいことですが、完全に理論上の話です。正確な Graphics2D が実際に描画される AttributedString がなければ、その FRC は役に立たないというよりも悪いので、すべての優れた情報はその FRC 内に効果的に閉じ込められます。これは、実際に受け入れようとする幻想です。

すべてが実行時に渡される Graphics2D に実際に依存しているため、これは理にかなっています。したがって、最善の方法は、それを受け入れて、paintComponent 内から呼び出して、実行する必要のあるオブジェクトや特殊な計算を呼び出すコードを記述し、これが現状であるという事実に基づいて設計を構築することです。

私は良い質問であり、できればいいのですが、できません。Web 上の他のフォーラムで、他の人がこれを求めているのを目にします。有用な回答がないこと、および/または耳をつんざくような沈黙に注意してください。

于 2014-06-14T02:40:38.733 に答える
2

もご覧くださいSwingUtilities.computeStringWidth

于 2011-02-06T16:54:34.833 に答える
1

を使用する以外FontMetricsに、を使用JLabelして、フォーマットされていないテキストと (基本的な HTML) レンダリングされたテキストの両方のサイズを決定できます。ここに例があります。

import java.awt.Color;
import java.awt.Dimension;
import java.awt.GradientPaint;
import java.awt.Graphics;
import java.awt.Graphics2D;

import java.awt.image.BufferedImage;

import javax.swing.JOptionPane;
import javax.swing.JLabel;
import javax.swing.ImageIcon;

/** Sample code obtained from a thread on the Oracle forums that I cannot
locate at this instant.  My question was related to an unexpected rendering of
JLabel.  It was resolved by the 'added this' line courtesy of Darryl Burke. */
public class LabelRenderTest {

  String title = "<html><body style='width: 160px; padding: 8px'>"
          + "<h1>Do U C Me?</h1>"
          + "Here is a long string that will wrap.  "
          + "The effect we want is a multi-line label.";

  LabelRenderTest() {
    BufferedImage image = new BufferedImage(
            640,
            480,
            BufferedImage.TYPE_INT_RGB);
    Graphics2D imageGraphics = image.createGraphics();
    GradientPaint gp = new GradientPaint(
            20f, 20f, Color.blue,
            620f, 460f, Color.white);
    imageGraphics.setPaint(gp);
    imageGraphics.fillRect(0, 0, 800, 600);

    JLabel textLabel = new JLabel(title);
    textLabel.setSize(textLabel.getPreferredSize()); // <==== added this

    Dimension d = textLabel.getPreferredSize();
    BufferedImage bi = new BufferedImage(
            d.width,
            d.height,
            BufferedImage.TYPE_INT_ARGB);
    Graphics g = bi.createGraphics();
    g.setColor(new Color(255, 255, 255, 128));
    g.fillRoundRect(
            0,
            0,
            bi.getWidth(null),
            bi.getHeight(null),
            15,
            10);
    g.setColor(Color.black);
    textLabel.paint(g);
    Graphics g2 = image.getGraphics();
    g2.drawImage(bi, 20, 20, null);

    ImageIcon ii = new ImageIcon(image);
    JLabel imageLabel = new JLabel(ii);

    JOptionPane.showMessageDialog(null, imageLabel);
  }

  public static void main(String[] args) {
    LabelRenderTest ist = new LabelRenderTest();
  }
}

編集1:「多くの文字列」のコメントについて。BufferedImage必要な場合にのみ再生成される に文字列をペイントします。paintComponent()が呼び出されるたびにバッファリングされたイメージを使用します。

于 2011-02-06T16:24:24.613 に答える
0

これは、同様のことを行うコードのスニペットです。これは、文字列を指定されたピクセル数に短縮するために記述されています。

public static String abbreviate(final Graphics2D g2, final String text, final int fitToWidth) {
     // define how many characters in the caption can be drawn
     final FontMetrics fm = g2.getFontMetrics();
     Rectangle2D textBounds = fm.getStringBounds(text, g2);
     int count = text.length();
     while ((textBounds.getWidth() > fitToWidth) && (count > 4)) {
         textBounds = fm.getStringBounds(text.substring(0, count--), g2);
     }
     return count == text.length() ? text : StringUtils.abbreviate(text, count);
}
于 2011-02-06T15:38:59.903 に答える
0

歴史的な理由から、彼が最初にそれを行ったと私が思う方法は次のとおりです(jruby java pseucodoe)

font = UIManager.getFont("Label.font")
frc = java.awt.font.FontRenderContext.new(font.transform, true, true)
textLayout = java.awt.font.TextLayout.new(text, font, frc)
textLayout.bounds.width
于 2012-05-21T23:52:40.060 に答える