0

Javaでカスタムテキストコンポーネントを作成するには? getPreferredSize()テキスト構造の測定値を入れる場所を提供する必要があります。しかし、最初に を取得せずにテキスト メトリックを測定することはできませんGraphicsGraphicsしかし、最初にコンポーネントをペイントしないと取得できません。しかし、コンポーネントを最初に測定しないと、コンポーネントをペイントすることはできません。

この悪循環を断ち切るには?

サンプルコード

public class Text_CustomTextual {

    public static class JHelloWorld extends JComponent {

        private final String content = "Hello world!";
        private final Font font = new Font(Font.SERIF, Font.PLAIN, 12);
        private Dimension dim = null;
        private FontMetrics fm;

        @Override
        public Dimension getPreferredSize() {

            // I can't measure control until I paint it once
            if( dim == null ) {
                return new Dimension(300,5); 
            }

            // I can measure it only after it was painter at least once
            else {
                return dim;
            }
        }

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

            g.setFont(font);

            // this is branch for first paint where I can measure control
            if( dim == null ) {

                // why should I have Graphics to measure font???
                fm = g.getFontMetrics(); 

                // why should I feed Graphics to getStringBound method???
                // did FontMetrics already forgot one I constructed it with???
                Rectangle2D rect = fm.getStringBounds(content, g);  
                dim = new Dimension((int)rect.getWidth(),(int)rect.getHeight());

                // how to cause control size to be reevaluated?
                // repaint() does not help, control remains 300x5
                repaint(); 
            }
            else {
                g.setColor(getForeground());
                g.drawString(content, 0, fm.getAscent());
            }
        }
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {

            @Override
            public void run() {

                final JHelloWorld h = new JHelloWorld();

                final JFrame f = new JFrame();
                f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                f.add(h);
                f.pack();
                f.setTitle(String.format("%dx%d", h.getWidth(), h.getHeight()));

                h.addComponentListener(new ComponentListener() {

                    @Override
                    public void componentShown(ComponentEvent e) {

                    }

                    @Override
                    public void componentResized(ComponentEvent e) {
                        f.setTitle(String.format("%dx%d", h.getWidth(), h.getHeight()));
                    }

                    @Override
                    public void componentMoved(ComponentEvent e) {
                    }

                    @Override
                    public void componentHidden(ComponentEvent e) {
                    }
                });

                f.setVisible(true);

            }
        });
    }
}
4

1 に答える 1

0

通常、優先サイズは動的に設定されません。ただし、ヒントとして、どのサイズを使用するのが望ましいか:

    String text = "Hello world!";
    Font font = new Font(Font.SERIF, Font.PLAIN, 12);       
    GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
    BufferedImage bufferedImage = new BufferedImage(1,1,BufferedImage.TYPE_INT_RGB);
    Graphics2D g2d = ge.createGraphics(bufferedImage);
    FontRenderContext frc = g2d.getFontRenderContext();
    GlyphVector glyphVector = font.createGlyphVector(frc, text);
    Rectangle2D rectangle2D = glyphVector.getLogicalBounds();
    double w = rectangle2D.getWidth();
    double h = rectangle2D.getHeight();
    System.out.println("width = "+w+"\theight = "+h);
于 2012-06-23T18:25:46.893 に答える