2011-02-06 18 views
10

मैं एप्लिकेशन लिखने की कोशिश कर रहा हूं जिसे जावा में ग्राफिक्स 2 डी क्लास का उपयोग करके कई तारों को आकर्षित करने की आवश्यकता है। मुझे प्रत्येक स्ट्रिंग ऑब्जेक्ट के आकार (प्रत्येक स्ट्रिंग की सटीक स्थिति की गणना करने के लिए) प्राप्त करने की आवश्यकता है। इतने सारे तार हैं कि इसे पेंट() विधि कहा जाता है और केवल मेरे प्रोग्राम की शुरुआत में एक बार किया जाना चाहिए (इसलिए मेरे पास अभी तक ग्राफिक्स 2 डी ऑब्जेक्ट नहीं है)। मुझे पता है कि एक विधि Font.getStringBounds() है लेकिन इसे एक पैरामीटर के रूप में FontRenderContext ऑब्जेक्ट की आवश्यकता है।जावा में स्ट्रिंग आकार प्राप्त करना (ग्राफिक्स ऑब्जेक्ट उपलब्ध किए बिना)

जब मैं अपने वस्तु बनाने की कोशिश की:

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

और फिर तार प्राप्त सीमा मैंने हमेशा जब मैं प्राप्त का उपयोग कर FontRenderContext Graphics2D.getFontRenderContext() रंग के अंदर विधि() विधि से विभिन्न आकारों मिल । मतभेद बड़े नहीं हैं (लगभग 1 ई -3) लेकिन मुझे आश्चर्य है कि इसमें कोई अंतर क्यों है?

हालांकि, क्या स्ट्रिंग के आकार प्राप्त करने के लिए कोई बेहतर और सुरक्षित तरीका है?

Thnx अग्रिम में किसी भी मदद के लिए!

उत्तर

6

FontMetrics कक्षा के साथ प्रयास करें; stringWidth विधि एक स्ट्रिंग का आकार देता है। एक उदाहरण:

JComponent c = getSomeKindOfJComponent(); 
FontMetrics fm = c.getFontMetrics(c.getFont()); // or another font 
int strw = fm.stringWidth("My text"); 
+3

स्ट्रिंगविड्थ स्ट्रिंग के वैध आकार को वापस नहीं करता है क्योंकि यह एंटी-एलियासिंग और अन्य विशेषताओं (जैसे वर्णों के बीच अंतर) पर विचार नहीं करता है। –

0

यहाँ कि कुछ ऐसा ही कोड का एक टुकड़ा है - पिक्सल की दी गई संख्या के लिए स्ट्रिंग abbreviating के लिए लिखा था।

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); 
} 
+0

यह मेरी आवश्यकता नहीं है - मैं ग्राफिक्स 2 डी ऑब्जेक्ट के बिना सटीक स्ट्रिंग सीमाएं प्राप्त करना चाहता हूं। –

+1

@ coder89 खैर .. ग्राफिक्स 2 डी उदाहरण के गुण एप्लिकेशन के जीवन चक्र से अलग हो सकते हैं। जैसा कि आपने काफी सही तरीके से इंगित किया है, आपको "एंटी-एलाइजिंग और अन्य फीचर्स" को ध्यान में रखना होगा, जो ग्राफिक्स 2 डी के विशिष्ट उदाहरण के बिना संभव नहीं है। – 01es

0

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। स्ट्रिंग्स को एक बुफर्ड इमेज में पेंट करें जो आवश्यक होने पर केवल पुन: उत्पन्न होता है। प्रत्येक बार paintComponent() कहा जाता है BufferedImage का उपयोग करें।

2

आप SwingUtilities.computeStringWidth देख सकते हैं।

+0

यह एक पूर्णांक के रूप में चौड़ाई देता है - मुझे कुछ और सटीक की आवश्यकता है –

0
ऐतिहासिक खातिर

, यहाँ मैं कैसे लगता है कि वह यह मूल रूप से किया था (JRuby जावा 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 
2

Nev-आह है। गोन-ना। होता है।

कारण यह है कि आप एफआरसी से जो प्रतिपादन और गणना कर रहे हैं वह ग्राफिक्स संदर्भ के लिए विशिष्ट है, यानी एक विशिष्ट ग्राफिक्स 2 डी ऑब्जेक्ट। जिसकी आप रुचि रखते हैं वह वह है जिसे आप रनटाइम पर सौंपे जाते हैं- यह किसी अन्य की तरह नहीं है (आपको लगता है)।

आप जितना आप कुछ अन्य Graphics2D से एक एफआरसी का उपयोग कर के रूप में चाहते हैं की गणना कर सकता है, लेकिन सभी सब शून्य के लिए अपने संगणना जब आप उन्हें Graphics2D paintComponent साथ कार्यावधि में इस्तेमाल करने की कोशिश जो Graphics2D आप है 'हाथ है, उपयोग करने जा रहे हैं, कोई फर्क नहीं पड़ता कि क्या।

तो, हाँ, यह अच्छा होगा लेकिन यह पूरी तरह से सैद्धांतिक है। उस अच्छी जानकारी को प्रभावी रूप से उस एफआरसी के अंदर बंद कर दिया गया है क्योंकि सटीक ग्राफिक्स 2 डी के बिना एट्रिब्यूटेड स्ट्रिंग वास्तव में तैयार की जा रही है, कि एफआरसी बेकार से भी बदतर है- यह एक भ्रम है जिसे आप वास्तव में गले लगाने की कोशिश कर सकते हैं।

यह समझ में आता है, क्योंकि सबकुछ वास्तव में ग्राफिक्स 2 डी पर निर्भर है, आपको रनटाइम पर सौंप दिया जाता है। तो सबसे अच्छी बात यह है कि इसे स्वीकार करें और पेंट के भीतर से कॉल करने के लिए अपना कोड लिखें, जो कुछ भी ऑब्जेक्ट्स और जो भी विशेष गणना आपको करना है और इस तथ्य के आसपास अपना डिज़ाइन बनाएं कि यह वही तरीका है।

मैं एक अच्छा सवाल और एक अच्छी बात है जो आप कर सकते हैं, बस, आप नहीं कर सकते। आप अन्य मंचों में अन्य लोगों को वेब पर कहीं और पूछने के लिए देखते हैं। उपयोगी उत्तरों की कमी और/या बहरापन मौन पर ध्यान दें।