2012-01-22 8 views
12

Para mi sorpresa, me acaba de descubrir que drawLine y drawRect no incluyen la posición final, es decir .:Lienzo 'drawLine y drawRect sin incluir la posición final?

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

o

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

no va a dibujar cualquier cosa.

Mi pintura se define como sigue:

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

He intentado definir mi pintura como FILL_AND_STROKE, pero no ayudaría.

DrawPaint de Android() javadoc ni siquiera muestra los parametros stopX y stopY!

Así, si quiero dibujar una línea vertical que va exactamente de BeginY a Endy (ambos inclusive), tengo que hacer lo siguiente:

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

en cuenta que yo no sumar 1 al final Posición X, solo para terminar Y (xstays lo mismo que quiero una línea vertical).

Mi dispositivo es HTC SENSE.

Edit: Simon, tienes razón, en lugar de hacerte una pregunta. Acabo de tratar de compartir mi sensación de sorpresa de que Android no hace lo que dicen sus documentos en un caso tan fundamental como el dibujo básico, y asegúrate que no cometí ningún error estúpido en mi camino.

hacerme más claro: javadoc de drawRect dice:

pública drawRect vacío (flotar a la izquierda, flotar arriba, flotar bien, flotar inferior, pintura Paint)

dibujar el Rect especificado mediante el pintura especificada El rectángulo se rellenará o enmarcará según el estilo de la pintura.

izquierda - El lado izquierdo del rectángulo que se puede extraer

superior - El lado superior del rectángulo que se puede extraer

derecha - El lado derecho del rectángulo que se puede extraer

inferior - la parte inferior del rectángulo que se puede sacar

pintura - la pintura que se usa para dibujar el rect

Así, al escribir

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

Espera un rectángulo cuyas esquinas están en (x1, y1); (x1, y2); (x2, y1) y (x2, y2).

Android dice: ¡mal! Estarán en (x1, y1); (x1, y2-1); (x2-1, y1) y (x2-1, y2-1).

Para los curiosos: establecer el recorte de tela:

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

luego tratar de dibujar un punto:

canvas.drawPoint(x1, y1, paint); 

y se obtiene un punto en la pantalla.

A continuación, intente en la esquina opuesta:

canvas.drawPoint(x2, y2, paint); 

no aparece nada. tampoco aparecerá nada en las 2 esquinas restantes:

canvas.drawPoint(x1, y2, paint); 


canvas.drawPoint(x2, y2, paint); 

¿Todavía no sorprende a usted gente?

Así que la conclusión es que Android trata derecho y inferior coordina tan exclusiva, lo que significa que, por ejemplo, al escribir:

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

Usted recibirá los límites de recorte de (x1, y1, x2 - 1, y2 - 1). Lo mismo ocurre con todos los métodos que tengan y coordenadas de fondo Rect/RectF objetos.

+0

¿Hay alguna pregunta aquí? Si desea dibujar un solo punto, utilice: http://developer.android.com/reference/android/graphics/Canvas.html # drawPoint (float,% 20float,% 20android.graphics.Paint) –

+1

Esto no es una pregunta, pero me alegra que esté aquí. Me ahorra haciendo experimentos para encontrar la respuesta a esta otra pregunta: http://stackoverflow.com/questions/3063892/canvas-clipping-right-right-bottom-edge-inclusive –

Respuesta

5

Su pregunta revela una inconsistencia en la API de dibujo de Android. Usted dice

Así, si quiero dibujar una línea vertical que va exactamente de BeginY a Endy (ambos inclusive), tengo que hacer lo siguiente:

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

en cuenta que no agregué 1 a la posición final X, solo para terminar Y (xstays lo mismo que quiero una línea vertical).

La frase entre paréntesis es en mi opinión la clave para entender la naturaleza de la incompatibilidad:

También puede añadir 1 a la posición X final (! O incluso a la posición de inicio X), y obtendrías exactamente la línea idéntica a píxeles. ¿Porqué es eso? Debido a que el algoritmo subyacente para transformar el concepto de "pixel izquierdo/píxel salido" de Android al concepto "comienzo y final píxel" es el siguiente (mostrado solo para x, para y es el mismo):

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; 
} 

el resultado de esto (en mi opinión subóptima) la conversión es que la línea

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

es exactamente paralela a

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

Creo que todo el mundo esperaría una especie de inversa V, ya que los puntos finales están separados por al menos 1 píxel (su distancia es de dos píxeles) y los puntos de partida son idénticos.

Pero probado en varios dispositivos y versiones de Android, la primera línea perfectamente vertical está en la columna de píxeles 149 y el segundo en la columna 150.

Por cierto: La transformación correcta de utilizar el "pixel comenzar y terminar en" - concepto es:

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

si su fondo es negro, añadir una declaración paint.setColor(Color.RED); y también que tenía pasan RectF rect = new RectF(100, 100, 100, 100); todos los puntos son los mismos, tratar RectF rect = new RectF(100, 100, 200, 200);

O para la línea canvas.drawLine(10, 10, 10, 10 + 15, paint);

0

Su rect debería funcionar aletas, trate de añadir algunos antecedentes, su línea ahora tiene un píxel, los dos últimos parámetros no son la longitud, es la posisión final.

1

Tu pregunta es esencialmente la respuesta para this. Gracias.

Yo, por mi parte, no estoy sorprendido por esto, y no lo quisiera de ninguna otra manera. He aquí por qué:

  • Es consistente con java.awt, javax.swing y otras API, así como los principales métodos de Java como String.substring(int, int) y List<?>.get(int).

  • Es compatible con android.graphics.RectF, que no se preocupa por los píxeles: ¿cómo puede tener una fracción de píxel?

  • El API es conveniente:

    • para un rectángulo de 40 × 30, instanciar Rect(0, 0, 40, 30)

    • Rect.right - Rect.left == Rect.width()

  • Las matemáticas y geometría son más fáciles de esta manera. Por ejemplo, si desea dibujar un rectángulo centrado dentro del lienzo:

 Rect clipBounds = canvas.getClipBounds() 
    int myRectWidth = 20; 
    int myRectHeight = 10; 
    int left = (clipBounds.width() - myRectWidth)/2; 
    int top = (clipBounds.height() - myRectHeight)/2; 
    int right = clipBounds.width() - left; // See how nice this is? 
    int bottom = clipBounds.height() - top; // This wouldn't work if bottom was inclusive! 
    canvas.drawRect(left, top, right, bottom);

La API es correcto; the API documentation, lamentablemente, simplemente carece de detalles.

(En realidad, se menciona en the detail for the Rect.contains(int, int) method. Es desafortunado que Google deje que el API por la puerta sin las variables de campo que ellas mismas sean documentados, sin embargo.)

+0

Este comportamiento NO es consistente con java.awt. Gráficos: si llama a g.drawLine (100, 100, 100, 100) obtendrá un solo píxel dibujado. También es un comportamiento particularmente estúpido, ya que no se puede trazar una línea que conecte dos puntos, como en cualquier otra API 2D, y para dibujar una línea de manera adecuada hay que recurrir a hacks como drawLine (...); drawPoint (.. start ..); drawPoint (.. end ..). La similitud con String and List es irrelevante. – Gilead

+0

@Gilead: Mi error: 'java.awt.Graphics.drawRect()' toma un argumento de ancho y alto, que encaja con mi punto anterior, sobre las matemáticas. También podría haber sido mejor para Android hacerlo de esa manera. Y tendremos que estar de acuerdo para estar en desacuerdo sobre si la consistencia con 'String' y' List' es relevante; Honestamente, creo que sería más fácil trabajar con la plataforma Android si no hubiera tantas incoherencias. –

+0

Este me ayudó a entender, pero me gustaría agregar algo: arriba = Distancia entre la parte inferior de la pantalla y la parte inferior del rectángulo. inferior = Distancia entre la parte superior de la pantalla y el borde superior del rectángulo. left = Distancia entre el borde izquierdo de la pantalla y el borde izquierdo del rectángulo. right = Distancia entre el borde derecho de la pantalla y el borde derecho del rectángulo. – AgentKnopf

Cuestiones relacionadas