画布“的drawLine和drawRect中不包括结束位置? [英] Canvas' drawLine and drawRect not including end position?

查看:335
本文介绍了画布“的drawLine和drawRect中不包括结束位置?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

要我惊讶的是我刚刚发现的drawLine和drawRect中不包括结束位置,即:

To my surprise I've just discovered that drawLine and drawRect don't include the ending position, i.e.:

canvas.drawLine(100, 100, 100, 100, paint);

RectF rect = new RectF(100, 100, 100, 100);
canvas.drawRect(rect, paint);

不会画什么。

won't draw anything.

我的涂料被定义如下:

Paint paint = new Paint();
paint.setAntiAlias(false);
paint.setStyle(Paint.Style.FILL);
return paint;

我试图定义我的涂料作为FILL_AND_STROKE,但它不会帮助。

I've tried defining my paint as FILL_AND_STROKE, but it wouldn't help.

Android的drawPaint()的javadoc甚至不列出stopX和stopY PARAMS!

Android's drawPaint() javadoc don't even list the stopX and stopY params!

所以,如果我想画的那张完全从beginY到恩迪(含)的垂直线,我一定要做到以下几点:

So, if I want to draw a vertical line that goes exactly from beginY to endY (inclusive), I have to do the following:

canvas.drawLine(constX, beginY, constX, endY + 1)

请注意,我没有加1到结束X位置,才结束Y(xstays相同的,因为我想一个垂直线)。

Notice that I didn't add 1 to the ending X position, only to ending Y (xstays the same as I want a vertical line).

我的设备是HTC SENSE。

My device is HTC SENSE.

编辑:西门,你是对的,而不是问一个问题,我只是想分享我的感觉惊讶的是Android不去做它的文档说在这样一个基本的情况下基本的绘图,并确保我没有做我的方式任何愚蠢的错误。

Simon, you're right, rather than asking a question I've just tried to share my feeling of surprise that Android does not do what its docs say in such a fundamental case as basic drawing, and make sure that I didn't do any stupid mistake on my way.

为了让自己更清楚:drawRect中的Javadoc说:

To make myself clearer: drawRect's javadoc says:

公共无效的drawRect(左浮动,浮动顶部,右浮动,浮动底,油漆涂料)

使用指定的油漆绘制指定的矩形。该矩形将被填充或基于涂料中的风格框架。

Draw the specified Rect using the specified paint. The rectangle will be filled or framed based on the Style in the paint.

左 - 要绘制矩形的左侧

left - The left side of the rectangle to be drawn

顶端 - 矩形的顶侧被吸入

top - The top side of the rectangle to be drawn

右键 - 右侧矩形要绘制

right - The right side of the rectangle to be drawn

底部 - 矩形的底侧被吸入

bottom - The bottom side of the rectangle to be drawn

漆 - 用于绘制矩形的油漆

paint - The paint used to draw the rect

因此​​,写作时

canvas.drawRect(x1, y1, x2, y2)

您希望其角处(X1,Y1)的矩形; (X1,Y2); (X2,Y1)和(x2,y2)上。

You expect a rectangle whose corners are at (x1, y1); (x1, y2); (x2, y1) and (x2, y2).

Android的说:错了!他们将在(X1,Y1); (X1,Y2-1); (X2-1,y1)和(X2-1,Y2-1)。

Android says: wrong! They will be at (x1, y1); (x1, y2-1); (x2-1, y1) and (x2-1, y2-1).

有关好奇的:设置画布剪裁:

For the curious ones: set the canvas clipping:

canvas.clipRect(x1, y1, x2, y2)

然后试着画一个点:

Then try to draw a point:

canvas.drawPoint(x1, y1, paint);

和你在屏幕上的一个点。

and you get a point on the screen.

然后尝试在对面的角落:

Then try in the opposite corner:

canvas.drawPoint(x2, y2, paint);

出现什么。什么都不会出现在剩下的2个角落,并可:

nothing appears. nothing will appear in the remaining 2 corners as well:

canvas.drawPoint(x1, y2, paint);


canvas.drawPoint(x2, y2, paint);

不过也不奇怪,你的乡亲?

Still not surprising to you folks?

所以得出的结论是,Android的治疗坐标排他性的,这意味着如写作时:

So the conclusion is that Android treats right and bottom coordinates as exclusive, meaning that e.g. when writing:

canvas.clipRect(x1, y1, x2, y2)

您将获得的剪裁边界(X1,Y1,X2 - 1,Y2 - 1)。同样的问题也与每一个方法,它的右侧坐标或矩形/ RectF 的对象。

You will get the clipping bounds of (x1, y1, x2 - 1, y2 - 1). The same goes with every method that takes right and bottom coordinates or Rect/RectF objects.

推荐答案

您的问题揭示了Android的绘图API中存在不一致。你说

Your question reveals an inconsistency in the drawing API of Android. You say

所以,如果我想画的那张完全从beginY到恩迪(含)的垂直线,我一定要做到以下几点:

So, if I want to draw a vertical line that goes exactly from beginY to endY (inclusive), I have to do the following:

canvas.drawLine(constX, beginY, constX, endY + 1)

     

请注意,我没有加1到结束X位置,才结束Y(xstays相同的,因为我想一个垂直线)。

Notice that I didn't add 1 to the ending X position, only to ending Y (xstays the same as I want a vertical line).

在括号中的句子在我看来,了解矛盾的性质的关键是:

The sentence in brackets is in my opinion the key to understand the nature of the inconsistency:

您也可以加1到结束X位置(或甚至开始X位置!),你会得到完全的逐像素的同一行。这是为什么?因为底层的算法,从Android的左像素/右像素输出-concept转换到开始和结束像素-concept如下(只显示的x,y的是相同的):

You also could add 1 to the ending X position (or even to the beginning X position!), and you would get exactly the pixel-wise identical line. Why is that? Because the underlying algorithm to transform from Android's "left pixel in/right pixel out"-concept to the "start and end pixel in"-concept is as follows (shown only for x, for y it's the same):

int left, top, right, bottom; // left/top pixel inclusive, right/bottom pixel exclusive
int x1, y1, x2, y2;           // x1/y1 and x2/y2 pixels inclusive

if ( left == right ) {
    x1 = x2 = left;
} else if ( left < right ) {
    x1 = left;
    x2 = right - 1;
} else {
    x1 = right;
    x2 = left - 1;
}

该操作的结果(在我看来亚最佳)变换是线

The result of this (in my opinion sub-optimal) conversion is that the line

canvas.drawLine(150, 150, 149, 160, paint);

是完全平行于

is exactly parallel to

canvas.drawLine(150, 150, 151, 160, paint);

我想每个人都会想到那种倒V,因为端点被至少1个像素分离(它们之间的距离是两个像素)和出发点是相同的。

I think everybody would expect kind of inverse V, since the end points are separated by at least 1 pixel (their distance being two pixels) and the starting points are identical.

但在各种设备和Android版本的测试,第一次完全垂直线是在像素列149和150列第二。

But tested on various devices and Android versions, the 1st perfectly vertical line is in pixel column 149 and the 2nd in column 150.

BTW:正确的转换使用开始和结束像素-concept是:

BTW: The correct transformation to use the "start and end pixel in"-concept is:

int x1, y1, x2, y2;           // x1/y1 and x2/y2 pixels inclusive

if ( x1 <= x2 )
    ++x2;
else
    ++x1;
if ( y1 <= y2 )
    ++y2;
else
    ++y1;
canvas.drawLine(x1, y1, x2, y2, paint);

这篇关于画布“的drawLine和drawRect中不包括结束位置?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆