在代号一的绘图中的给定位置写入字符串

Writing a string at a given position in a drawing in Codename one

我正在构建一个应用程序,有时我会使用带有分层布局的表单。在这个表格中,我已经有 2 个标签堆叠在一起,我想在特定区域写一个字符串。

第一个图像(最深的图像)是来自设备相机的图像,第一个图像之上的第二个图像是具有 transparent 背景的 png 文件。它们都具有比屏幕分辨率更大的分辨率,这就是为什么我使用以下代码来显示它们的原因:

findPhotoBase3().getUnselectedStyle().setBackgroundType(Style.BACKGROUND_IMAGE_SCALED_FIT);
findDecoration3().getUnselectedStyle().setBackgroundType(Style.BACKGROUND_IMAGE_SCALED_FIT);
findPhotoBase3().getUnselectedStyle().setBgImage(montage.getBaseImage());
findDecoration3().getUnselectedStyle().setBgImage(montage.getdecorationImageSelected());

由于 2 张图片被缩放以适应屏幕大小,在横向模式下,两张图片都没有覆盖整个宽度(这是很正常的,因为原始图片比例保持不变)。因此,部分堆叠图像上有空白列。

我知道我的字符串应该从原始图像宽度的 xx %(这里是装饰)和原始高度的 yy % 开始。因此,我首先需要知道 (0, 0) 点所在的位置。

因此,如果我向 parent 表单添加一个新组件:

findDecoration3().getParent().add(new Component(){

      @Override
      public void paint(Graphics g) {
          g.drawString(".", 0 , 0 );
      }
}

然后该点绘制在堆叠图像的左侧,比图像左上角低一点。我已经像这样计算了 x 和 y 偏移量:

int originalImageWidth = findPhotoBase3().getUnselectedStyle().getBgImage().getWidth();
int originalImageHeight = findPhotoBase3().getUnselectedStyle().getBgImage().getHeight();
float ratioOriginal = (float) originalImageWidth / originalImageHeight;

// L'espace disponible dans le containeur parent
int availableWidth = findPhotoBase3().getParent().getWidth();
int availableHeight = findPhotoBase3().getParent().getHeight();

// Landscaped mode assumed
final int displayedImageWidth = (int) (ratioOriginal * availableHeight) ;
final int displayedImageHeight = availableHeight ;

// L'image débute à (coordonnées par rapport au container parent see chapter 9.10 of https://www.codenameone.com/files/developer-guide.pdf ) 
final int imageStartX0 = (availableWidth - displayedImageWidth) / 2;
// L'image prend toute la hauteur, donc elle commence à 0 dans le container parent
final int imageStartY0 = 0;

然而,显示的 0 点 (imageStartX/Y0) 并不位于正确的位置(即恰好位于 photoBase 图像的左上角),而是在两个方向上都具有正偏移。

该点如前所示绘制:

 g.drawString(".", imageStartX0 , imageStartY0 );

这是我得到的结果(使用了私人照片,所以只显示了一部分):

请注意,图片上出现了一个带圆圈的复选按钮。此按钮位于图像顶部的容器上。我没有提到它是为了让我的问题尽可能清楚。

因此,如果我无法获得正确的 0 点,我将无法在预期的位置写入我的字符串!

编辑 1

所以我尝试应用 Shai 给出的建议,并在图像区域周围绘制一个矩形,如下所示:

@Override
public void paint(Graphics g) {

    int color = 0xFF0000;
    g.setColor(color);
    g.drawRect(imageStartX0 + getX(), imageStartY0 + getY(), displayedImageWidth, displayedImageHeight); // This red rectangle is expected to be around the image just on its border

    color = 0x0000ff;
    g.setColor(color);
    g.drawString(".", getX() ,getY() ); // This blue point is expected to be on the upper left corner of the parent container

}

得到的是下面的图片。令我印象深刻的是,蓝点似乎并不完全位于 parent 容器的左上角(我想应该更靠上一点)。看起来 Y-axis 上有一个翻译导致了这个偏移。但是应用以下内容 not 有什么不同:

g.drawString(".", getX() - g.getTranslateX() ,getY() - g.getTranslateY() );

同样让我印象深刻的是,图像从预计位于容器左上角的蓝点开始 "above"(北方向)。那么 child 是否有可能在其 parent 的容器之外绘制? => 参见编辑 2(它确实不是从上面开始的)。

另一方面,我对显示图像尺寸的计算似乎存在缺陷,因为矩形比图像窄。因此,我将不得不以更简洁的方式计算它。 => 请参阅编辑 2(计算正常,但看起来 parent 容器的尺寸必须计算 inside 绘制方法)。

编辑 2

再次阅读 Shai 的回答我尝试画一个矩形(而不是写一个点字符):

g.fillRect(getX() - g.getTranslateX(), getY() - g.getTranslateY(), 5, 5);
g.drawRect(getX() - g.getTranslateX() ,getY() - g.getTranslateY(), 5, 5 );

它按预期工作(蓝点在左上角):

所以这应该与 drawString 的 JavaDoc 有关

The font is drawn from the top position and not the baseline.

它解释了为什么点不在预期位置(我的错!)。

总而言之,虽然我不清楚,但我可以通过移动部分代码(即关于 parent 容器尺寸的部分)inside paint 方法而不是外面。所以我的绘画方法现在看起来像:

@Override
public void paint(Graphics g) {
    // L'espace disponible dans le containeur parent
    // CAUTION : This has to be done in the paint method not outside
    int availableWidth = getWidth();
    int availableHeight = getHeight();

    // On fait l'hypothèse du mode paysage
    int displayedImageWidth = (int) (ratioOriginal * availableHeight) ;
    int displayedImageHeight = availableHeight ;

    // On récupère les coordonnées de l'image
    // L'image débute à (coordonnées par rapport au container parent) 
    int imageStartX0 = (availableWidth - displayedImageWidth) / 2;
    // L'image prend toute la hauteur, donc elle commence à 0 dans le container parent
    int imageStartY0 = 0;


    int colorNom = 0xFF0000;
    g.setColor(colorNom);
    g.drawRect(imageStartX0 + getX(), imageStartY0 + getY(), displayedImageWidth, displayedImageHeight);

    colorNom = 0x0000ff;
    g.setColor(colorNom);   
    g.drawString(nom, syntheStartX0 , syntheStartY0 - g.getTranslateY());
    g.fillRect(getX() - g.getTranslateX(), getY() - g.getTranslateY(), 5, 5);
    g.drawRect(getX() - g.getTranslateX() ,getY() - g.getTranslateY(), 5, 5 );

非常感谢任何能告诉我为什么我没有得到预期结果(即恰好在左上角的点)的人?

此致

Codename One 中的组件位于其父 Container 的 X/Y 中,未转换为位置。所以 0, 0 位置将是 getX(), getY().

您显然可以使用 translate 让 0,0 也为您工作。

The x and y coordinates that are passed to the drawRect(x,y,w,h) method are relative to the component’s parent’s origin — not the component itself .. its parent. This is why we the x position is getX()+5 and not just 5.

来自the Codename One Developer Guide Graphics section