为什么drawString方法似乎并不总是从给定的坐标开始?

时间:2016-06-13 04:40:56

标签: drawing codenameone dpi

在我的代码中,我无法在精确坐标处绘制字符串。它的左上角不是从给定坐标开始,而是从其他地方开始。但是,如果我从相同的给定坐标绘制一个矩形,它就可以很好地放置。这种行为怎么可能呢?

这是我在beforeShow()方法中调用的代码:

Image photoBase = fetchResourceFile().getImage("Voiture_4_3.jpg");
    Image watermark = fetchResourceFile().getImage("Watermark.png");


    f.setLayout(new LayeredLayout());
    final Label drawing = new Label();
    f.addComponent(drawing);


    // Image mutable dans laquelle on va dessiner (fond blancpar défaut)
    Image mutableImage = Image.createImage(photoBase.getWidth(), photoBase.getHeight());

    // Paint all the stuff
    paintAll(mutableImage.getGraphics(), photoBase, watermark, photoBase.getWidth(), photoBase.getHeight());


    drawing.getUnselectedStyle().setBgImage(mutableImage);
    drawing.getUnselectedStyle().setBackgroundType(Style.BACKGROUND_IMAGE_SCALED_FIT);


    // Save the graphics
    // Save the image with the ImageIO class
    long time = new Date().getTime();
    OutputStream os;
    try {
        os = Storage.getInstance().createOutputStream("screenshot_" + Long.toString(time) + ".png");
        ImageIO.getImageIO().save(mutableImage, os, ImageIO.FORMAT_PNG, 1.0f);
    } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }

paintAll方法

public void paintAll(Graphics g, Image background, Image watermark, int width, int height) {

    // Full quality
    float saveQuality = 1.0f;

    // Create image as buffer
    Image imageBuffer = Image.createImage(width, height, 0xffffff);
    // Create graphics out of image object
    Graphics imageGraphics  = imageBuffer.getGraphics();

    // Do your drawing operations on the graphics from the image
    imageGraphics.drawImage(background, 0, 0);
    imageGraphics.drawImage(watermark, 0, 0);

    imageGraphics.setColor(0xFF0000);

    // Upper left corner
    imageGraphics.fillRect(0, 0, 10, 10);

    // Lower right corner
    imageGraphics.setColor(0x00FF00);
    imageGraphics.fillRect(width - 10, height - 10, 10, 10);

    imageGraphics.setColor(0xFF0000);
    Font f = Font.createTrueTypeFont("Geometos", "Geometos.ttf").derive(220, Font.STYLE_BOLD);
    imageGraphics.setFont(f);
    // Draw a string right below the M from Mercedes on the car windscreen (measured in Gimp)
    int w = 0, h = 0;

    imageGraphics.drawString("HelloWorld", w, h);


    // Coin haut droit de la string
    imageGraphics.setColor(0x0000FF);
    imageGraphics.fillRect(w, h, 20, 20);

    // Draw the complete image on your Graphics object g (the screen I guess) 
    g.drawImage(imageBuffer, 0, 0);


}

w = 0,h = 0(无明显偏移)的结果: no offset

w = 841,h = 610的结果(两个轴上都出现偏移:挡风玻璃上的梅赛德斯M附近的蓝点与Hello World字符串之间存在偏移) with offset

EDIT1: 我还为Android阅读了此SO question,建议将dpi转换为像素。它也适用于Codename One吗?如果是这样我怎么能这样做?我试过了

Display.getInstance().convertToPixel(measureInMillimeterFromGimp)

没有成功(我使用mm,因为javadoc告诉dpi大约是1毫米)

任何帮助将不胜感激,

干杯

2 个答案:

答案 0 :(得分:1)

gimageGraphics都是两次创建的相同图形,可能会产生一些影响(不太确定)......

在完成绘制之前,您还可以将可变图像设置为样式的背景。我不知道这是否是你所看到的奇怪的原因,但我会怀疑代码。

答案 1 :(得分:0)

灵感来自Gabriel Hass' answer我最终使用另一个中间图像使其仅在(0; 0)处写入字符串,然后在imageBuffer图像上绘制此图像,现在在右边坐标处。它可以工作,但在我看来drawString(图像,坐标)应该直接绘制在给定的坐标,不应该@Shai?

String eventually at the righ coordinates (blue point expected to be on the top left corner of String HelloWorld

这是paintAll我用来解决我的问题的方法(beforeShow代码没有改变):

    // Full quality
    float saveQuality = 1.0f;

    String mess = "HelloWorld";

    // Create image as buffer
    Image imageBuffer = Image.createImage(width, height, 0xffffff);
    // Create graphics out of image object
    Graphics imageGraphics  = imageBuffer.getGraphics();


    // Do your drawing operations on the graphics from the image
    imageGraphics.drawImage(background, 0, 0);
    imageGraphics.drawImage(watermark, 0, 0);

    imageGraphics.setColor(0xFF0000);

    // Upper left corner
    imageGraphics.fillRect(0, 0, 10, 10);

    // Lower right corner
    imageGraphics.setColor(0x00FF00);
    imageGraphics.fillRect(width - 10, height - 10, 10, 10);


    // Create an intermediate image just with the message string (will be moved to the right coordinates later)
    Font f = Font.createTrueTypeFont("Geometos", "Geometos.ttf").derive(150, Font.STYLE_BOLD);
    // Get the message dimensions 
    int messWidth = f.stringWidth(mess);
    int messHeight = f.getHeight();

    Image messageImageBuffer = Image.createImage(messWidth, messHeight, 0xffffff);
    Graphics messageImageGraphics  = messageImageBuffer.getGraphics();

    messageImageGraphics.setColor(0xFF0000);
    messageImageGraphics.setFont(f);

    // Write the string at (0; 0)
    messageImageGraphics.drawString(mess, 0, 0);

    // Move the string to its final location right below the M from Mercedes on the car windscreen (measured in Gimp) 
    int w = 841, h = 610;   
    imageGraphics.drawImage(messageImageBuffer, w, h);


    // This "point" is expected to be on the lower left corner of the M letter from Mercedes and on the upper left corner of the message string
    imageGraphics.setColor(0x0000FF);
    imageGraphics.fillRect(w, h, 20, 20);

    // Draw the complete image on your Graphics object g 
    g.drawImage(imageBuffer, 0, 0);