2012-06-23 18 views
0

如何在Java中製作自定義文本組件?我需要爲其提供getPreferredSize(),其中我應該對我的文本構造進行測量。但是,如果沒有先獲得Graphics,我就無法測量文字指標。但是我不能先取得零件Graphics。但是如果不先測量它,我就不能繪製組件。如何製作自定義文本組件?

如何打破這個惡性循環?

示例代碼

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); 

      } 
     }); 
    } 
} 
+0

令人困惑。我建議你在這個問題關閉之前加入一個[sscce](http://www.sscce.org)。 – user1329572

+0

哪部分代碼*特別*給你帶來麻煩?我可以發現一些邏輯錯誤。 – user1329572

+0

問題是循環依賴。它不能歸因於代碼中的某個特定位置。 –

回答

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);