【问题标题】:How to accurately get the width of a drawn String (in pixel) with Codename One?如何使用 Codename One 准确获取绘制字符串的宽度(以像素为单位)?
【发布时间】:2016-06-24 17:44:14
【问题描述】:

我正在尝试在 Codename One 中的图像上精确放置一个短文本。我根据文本的宽度计算文本应该开始的位置,以便它看起来居中。

但是我从

得到的文本宽度
myFont.stringWidth(myStringToMeasure);

总是比实际绘制的文本大得多(在绘制文本的 Graphics 周围绘制一个矩形)。因此,文本看起来根本不居中。这是我从模拟器中得到的。

我尝试将 myString 中每个字符的宽度与

相加
for (char c : myString.toCharArray()) {
     stringWidth += myFont.charWidth(c);
}

但结果比前一个更大(几乎是原来的两倍)。

我是否误用了 stringWidth 方法?有没有办法可靠地获取绘制字符串的宽度?

NB:我刚刚在设备上尝试过,文本看起来符合预期。是我运气好还是可以在其他真实设备上运行?

编辑 1:

这很奇怪,我知道@Shai 是对的,但我无法让它发挥作用!如果我只是在我的方法中加入他的代码 sn-p 我会得到完全不同的结果:

    // width and height are the Graphics width and height that
    // has been created via Image.createImage(myImage.getWidth(), myImage.getHeight())
    public void paintOnBackground(Graphics g, 
        int width, int height) {

     Font myFont = g.getFont();
        g.setFont(myFont);
        int w = myFont.stringWidth("Hi World");
        int h = myFont.getHeight();

        // Added just to see the background
        g.setColor(0x0000FF);
        g.fillRect(0, 0, width, height);

        g.setColor(0xff0000);
        // Because g.getTranslateX() is equivalent to getX() (not available here)
        int x = g.getTranslateX() + width / 2 - w / 2;
        int y = g.getTranslateY() + height / 2 - h / 2;

        // The rectangle is centered
        g.drawRect(x, y, w, h, 20); // large thickness to see it at a glance!
        // The string is outside the rectangle
        g.drawString("Hi World", x, y);

我什至没有得到@Shai 的结果:

知道我做错了什么吗?

编辑 2:好的,如果我在设备 (Android 4.4) 上对其进行测试,则字符串将显示为 Shai 的屏幕截图。 所以看起来这是一个与模拟器相关的问题(所有皮肤/Linux/Eclipse 4.5)! Shai 的代码(实际上也是我的)在真实设备上运行良好。

编辑 3:问题已解决:将项目库从 114 升级到 115 解决了问题 => 请参阅 this other SO question which was related

任何帮助将不胜感激!

干杯

【问题讨论】:

    标签: drawing codenameone


    【解决方案1】:

    根据定义,字符宽度将不准确,因为字符可能单独绘制不同。

    当使用相同的 Font 对象时,字符串的宽度在任何地方都应该是完全准确的:

    Form f = new Form("Width", new BorderLayout());
    f.add(BorderLayout.CENTER, new Component() {
    
        @Override
        protected void initComponent() {
            super.initComponent(); 
            setUIID("Label");
        }
    
    
        @Override
        public void paint(Graphics g) {
            Font myFont = getStyle().getFont();
            g.setFont(myFont);
            int w = myFont.stringWidth("Hi World");
            int h = myFont.getHeight();
            g.setColor(0xff0000);
            int x = getX() + getWidth() / 2 - w / 2;
            int y = getY() + getHeight() / 2 - h / 2;
            g.drawRect(x, y, w, h);
            g.drawString("Hi World", x, y);
        }
    
    });
    f.show();
    

    使用不同的字体...

    @Override
    protected void initComponent() {
        super.initComponent(); 
        setUIID("Label");
        Font handleeFont = Font.createTrueTypeFont("Handlee", "Handlee-Regular.ttf").
                        derive(Font.getDefaultFont().getHeight(), Font.STYLE_PLAIN);
        Font handleeFontLarge = handleeFont.derive(handleeFont.getHeight() * 1.5f, Font.STYLE_PLAIN);
        getUnselectedStyle().setFont(handleeFontLarge);
    }
    

    【讨论】:

    • 谢谢@Shai。我正在使用相同的字体对象,但我创建了像 Font font = Font.createTrueTypeFont(myFontFeatures.get("FontName_Name"), myFontFeatures.get("FontName_Name") + ".ttf").derive(fontSize, styleName); 这样的 ttf 字体。这可能是我得到与你不同的结果的原因吗?我会检查我是否在某个地方做错了。
    • 谢谢 Shai,我在我的代码中尝试了你的第一个 sn-p。即使这样,我也会得到不同的结果(请参阅我的编辑)!我可能在某处改变了一些导致这种行为的东西......但我不知道是什么!
    • 您的屏幕截图是从真实设备@Shai 获取的吗?因为对我来说它在我的设备上按预期工作。看起来我描述的行为只出现在模拟器上(所有皮肤)。
    • 截图来自模拟器,使用的是厨房水槽演示中的 Handlee 字体
    • 好的,那是什么导致我的模拟器与你的结果不同以及真实设备上出现的结果是什么?也许在我的模拟器或 Eclipse 上配置错误?
    猜你喜欢
    • 1970-01-01
    • 2013-06-17
    • 1970-01-01
    • 2011-09-24
    • 1970-01-01
    • 2013-08-22
    • 2011-06-28
    • 2011-09-15
    • 1970-01-01
    相关资源
    最近更新 更多