c# - sacar - ejercicios de ejes cartesianos secundaria
Obtener las coordenadas de un punto de dibujo de valores de tabla en cuadros de texto? (1)
En el diseñador tengo dos TextBoxes. Y también un control de gráfico. Quiero que cuando escriba la primera caja de texto el número 120 y en la segunda escriba el número 1 dibuje un punto en la tabla en 120,1, pero me refiero a 120 y 1 como valores del eje xy del eje y.
El círculo relleno de rojo no está en 120 y 1. Quiero decir que el círculo rojo debe dibujarse en el eje izquierdo en 120. Y si voy a poner en su lugar 120 116 y en su lugar 1 25, entonces el círculo debe dibujarse en el eje izquierdo 116 y en el eje inferior el 25.
Pero ahora el círculo se extrae de la tabla.
Este es mi código:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Windows.Forms.DataVisualization.Charting;
using System.Drawing.Drawing2D;
using System.Collections;
namespace Test
{
public partial class Form1 : Form
{
private Point startPoint = new Point();
private Point endPoint = new Point();
private int X = 0;
private int Y = 0;
private List<Point> points = new List<Point>();
private Point lastPoint = Point.Empty;
private ArrayList myPts = new ArrayList();
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
Random rdn = new Random();
for (int i = 120; i > 0; i--)
{
chart1.Series["Series1"].Points.AddXY
(rdn.Next(0, 10), rdn.Next(0, 10));
}
chart1.Series["Series1"].ChartType = SeriesChartType.FastLine;
chart1.Series["Series1"].Color = Color.Red;
ChartArea area = chart1.ChartAreas[0];
area.AxisX.Minimum = 1;
area.AxisX.Maximum = 30;
area.AxisY.Minimum = 1;
area.AxisY.Maximum = 120;
LineAnnotation line = new LineAnnotation();
Point p1 = new Point(1, 120);
chart1.Annotations.Add(line);
line.AxisX = area.AxisX;
line.AxisY = area.AxisY;
line.IsSizeAlwaysRelative = false;
line.X = 1; line.Y = 120;
line.Right = 30; line.Bottom = 1;
line.LineColor = Color.Blue;
line.LineWidth = 3;
}
SolidBrush myBrush = new SolidBrush(Color.Red);
private void chart1_Paint(object sender, PaintEventArgs e)
{
Graphics g = e.Graphics;
foreach (Point p in myPts)
g.FillEllipse(myBrush, p.X, p.Y, 10, 10);
}
private void chart1_MouseClick(object sender, MouseEventArgs e)
{
myPts.Add(new Point(X,Y));
chart1.Invalidate();
}
private void txtT_TextChanged(object sender, EventArgs e)
{
X = int.Parse(txtWeight.Text);
}
private void txtDays_TextChanged(object sender, EventArgs e)
{
Y = int.Parse(txtDays.Text);
}
}
}
Lo que hice fue que después de ingresar ambos valores en los cuadros de texto, cuando hago clic en cualquier lugar en el área de control del gráfico con el mouse, debería dibujar el circuito en las coordenadas de los cuadros de texto.
Pero el círculo no está dibujando en el lugar correcto.
El nombre textBox txtT es el izquierdo el eje en los valores izquierdos. El textBox txtDays debería ser el eje en los valores inferiores.
La tarea de traducir coordenadas de dibujo en DataPoints y viceversa no es exactamente intuitiva.
Es posible, pero necesita conocer las reglas y pagar un cierto precio.
He esbozado el camino en esta publicación y vale la pena investigar ...
Pero como el problema está apareciendo repetidamente, aquí hay una solución más general.
Aquí es cómo llamarlo:
private void button11_Click(object sender, EventArgs e)
{
valuePoints.Add(new PointF(640, 1));
valuePoints.Add(new PointF(670, 10));
paintToCalaculate = true;
chart1.Invalidate();
}
Y aquí está el resultado: dos puntos rojos dibujados en los valores 640, 1
y 670, 10
:
Los puntos se colocan correctamente a pesar de que he ampliado y desplazado en el gráfico y también lo cambio de tamaño.
Para que funcione, necesitamos tres variables de nivel de clase: una bandera y dos listas de puntos. Una lista es la entrada con los valores en el gráfico donde están los puntos, la otra es la salida, que recibe las coordenadas de píxeles actuales.
bool paintToCalaculate = false;
List<Point> drawPoints = new List<Point>();
List<PointF> valuePoints = new List<PointF>();
Utilizo una bandera para evitar volver a calcular los puntos cuando el sistema causa redraws. Y después de configurarlo desencadenar el evento de Paint
al Invalidating
el Chart
. Durante el evento Paint
reinicié la bandera.
Tenga en cuenta que estos valores son muy volátiles : cambian:
- Cada vez que acerca o desplaza
- Siempre que cambie el tamaño del gráfico
- Cuando el diseño cambia, tal vez porque los nuevos puntos necesitan espacio o provocan un cambio en el formato de la etiqueta.
¡Por lo tanto, esas coordenadas de dibujo tendrán que actualizarse en cada uno de esos eventos!
Aquí hay un ejemplo, que se encarga de hacer zoom y desplazarse:
private void chart1_AxisViewChanged(object sender, ViewEventArgs e)
{
paintToCalaculate = true;
chart1.Invalidate();
}
Necesita agregar estas dos líneas, o una función para envolverlas, en algunos otros puntos de su programa, dependiendo de qué cosas permita que sucedan en el gráfico. Resize
también es un candidato obvio.
Ahora para el cálculo real. Está utilizando ValueToPixelPosition
, que hace todo el trabajo. Lamentablemente, solo funciona dentro de cualquiera de los tres eventos de pintura de un gráfico ( PrePaint
, Paint
y PostPaint
). Aquí uso el evento Paint
normal.
private void chart1_Paint(object sender, PaintEventArgs e)
{
if (paintToCalaculate)
{
Series s = chart1.Series.FindByName("dummy");
if (s == null) s = chart1.Series.Add("dummy");
drawPoints.Clear();
s.Points.Clear();
foreach (PointF p in valuePoints)
{
s.Points.AddXY(p.X, p.Y);
DataPoint pt = s.Points[0];
double x = chart1.ChartAreas[0].AxisX.ValueToPixelPosition(pt.XValue);
double y = chart1.ChartAreas[0].AxisY.ValueToPixelPosition(pt.YValues[0]);
drawPoints.Add(new Point((int)x, (int)y));
s.Points.Clear();
}
paintToCalaculate = false;
chart1.Series.Remove(s);
}
//..
// now we can draw our points at the current positions:
foreach (Point p in drawPoints)
e.Graphics.FillEllipse(Brushes.Red, p.X - 2, p.Y - 2, 4, 4);
}
Tenga en cuenta que agrego y elimino una Series
ficticia y le agrego y borro un Point
para cada punto de datos, solo para calcular sus coordenadas de píxel. Sí, un poco involucrado, pero los resultados valen la pena.
Supongo que puede cambiar el código Button_Click
para leer los valores de sus TextBoxes
lugar de usar mis números codificados.