c# - graficos - Anchura de anotación rectangular de gráfico MS en porcentaje y no en píxeles
graficas c# windows form (2)
¿Por qué el ancho de la anotación rectangular de la tabla MS está en porcentaje y no en píxeles, como dice msdn? https://msdn.microsoft.com/en-us/library/system.windows.forms.datavisualization.charting.annotation.width(v=vs.110).aspx
Esto es lo que dice msdn Obtiene o establece el ancho, en píxeles, de una anotación.
Me gustaría establecer mi ancho en píxeles como dice. ¿Me estoy perdiendo de algo?
¡Felicidades, has encontrado un error en la documentación! Fácil de detectar simplemente siguiendo el enlace a la anotación . Documentos de altura.
Las dimensiones de una Annotation
, como muchas otras en un control de Chart
, se dan en porcentajes . Esto tiene la ventaja de que crecen y contraen con bastante inteligencia con el control Chart
al igual que muchos otros elementos.
Entonces, si duplicas el ancho del gráfico, básicamente doblas el espacio para los DataPoints
mostrados y si tu Annotation
superó un 1/3 del ancho antes de que siga haciéndolo después de que hayas cambiado el tamaño del gráfico.
Lo cual es bueno.
Pero no es lo que querías ...
Por lo tanto, para establecer el tamaño a un tamaño fijo en píxeles, debe hacer esto:
- Calcule el tamaño que desea en porcentajes y configúrelo
- Repita cada vez que cambie el tamaño del gráfico o su diseño
El verdadero problema es el cálculo: si miras Chart.ClientSize
, obtienes el tamaño en píxeles y para obtener n píxeles necesitas hacer algo como esto:
float WidthInPercent = 100f * n / Chart.ClientSize.width;
Sin embargo, esto no tiene en cuenta los diversos elementos que probablemente tenga su Chart
: El Size
de una Annotation
no se calcula realmente como porcentajes directos del tamaño del gráfico.
En cambio, se califica como porcentajes de la InnerPlotPosition
de InnerPlotPosition
de ChartArea CA
InnerPlotPosition
está configurado de forma predeterminada en Auto
para acceder a sus valores, por ejemplo, CA.InnerPlotPosition.Width
devolverá 0f
; pero puede obtener los valores (¡actuales!) haciendo esto:
RectangleF IPP = CA.InnerPlotPosition.ToRectangleF();
Lo mismo vale para el Size/Position
de la propia ChartArea
:
RectangleF CAP = CA.Position.ToRectangleF();
Ahora puede combinar estos porcentajes con el Chart.ClientSize
( actual! ) Chart.ClientSize
averiguar qué porcentaje necesita para alcanzar un determinado tamaño de píxel.
Tenga en cuenta que estos valores cambiarán al cambiar el tamaño porque los extras externos, como Legend
y Axis
and Labels
etc. no cambiarán de tamaño, por lo que sus tamaños relativos crecerán o parpadearán en relación con los elementos que los contienen.
Por lo tanto , debe volver a calcular cada vez que cambie el Resize
evento o, mejor aún, escriba una función para que lo haga, a la que puede llamar cuando lo necesite.
El resultado es una Annotation
que (prácticamente, debido al redondeo) mantendrá su tamaño, sin importar cómo cambie el tamaño del Chart
.
Aquí hay algunas funciones útiles:
Éste devuelve el ClientRectangle
de ClientRectangle
actual de un área de ChartArea
en píxeles
RectangleF ChartAreaClientRectangle(Chart chart, ChartArea CA)
{
RectangleF CAR = CA.Position.ToRectangleF();
float pw = chart.ClientSize.Width / 100f;
float ph = chart.ClientSize.Height / 100f;
return new RectangleF(pw * CAR.X, ph * CAR.Y, pw * CAR.Width, ph * CAR.Height);
}
Este es similar y devuelve el ClientRectangle
de ClientRectangle
actual de una ChartArea''s InnerplotPosition
en píxeles:
RectangleF InnerPlotPositionClientRectangle(Chart chart, ChartArea CA)
{
RectangleF IPP = CA.InnerPlotPosition.ToRectangleF();
RectangleF CArp = ChartAreaClientRectangle(chart, CA);
float pw = CArp.Width / 100f;
float ph = CArp.Height / 100f;
return new RectangleF(CArp.X + pw * IPP.X, CArp.Y + ph * IPP.Y,
pw * IPP.Width, ph * IPP.Height);
}
Por último, uno que convierte un tamaño en píxeles a uno en porcentajes, nuevamente válido solo en la actualidad, es decir, hasta los siguientes cambios de tamaño o diseño:
SizeF Pixels2Percent( ChartArea CA, int w, int h)
{
RectangleF IPPR = InnerPlotPositionClientRectangle(chart1, CA);
float pw = 100f * w / IPPR.Width ;
float ph = 100f * h / IPPR.Height ;
return new SizeF(pw, ph);
}
Echemos un vistazo al resultado antes y después de cambiar el tamaño:
Como puede ver, el tamaño permanece igual.
¡También tenga en cuenta los rectángulos coloreados que dibujo en el evento Paint
para demostrar las nuevas funciones!
Aquí está el evento Paint
:
private void chart1_Paint(object sender, PaintEventArgs e)
{
ChartArea CA = chart1.ChartAreas[0];
e.Graphics.DrawRectangle(Pens.Violet,
Rectangle.Round(ChartAreaClientRectangle(chart1, CA)));
e.Graphics.DrawRectangle(Pens.LimeGreen,
Rectangle.Round(InnerPlotPositionClientRectangle(chart1, CA)));
}
Aquí está el evento de Resize
:
private void chart1_Resize(object sender, EventArgs e)
{
sizeAnn(ra, new Size(24, 36));
}
Y aquí la función de dimensionamiento:
void sizeAnn(RectangleAnnotation ra, Size sz)
{
ChartArea CA = chart1.ChartAreas[0];
SizeF pixelPercent = Pixels2Percent(CA, sz.Width, sz.Height);
ra.Width = pixelPercent.Width;
ra.Height = pixelPercent.Height;
}
Sí, no podemos configurarlo en% o px ya que el valor de la propiedad se establece en el doble. En segundo lugar, pixle = H multiplicado por W. pero solo está configurando el ancho del gráfico, ¿cómo puede establecerlo en pixeles? Fundamentalmente no es posible. Espero que entiendas lo que quiero decir.